Преобразование серии xarray.DataArrays в массив NumPy
Я использую пакет под названием PySD для моделирования системной динамики. PySD преобразует модели из Vensim (пакет моделирования системной динамики) в python и позволяет пользователю заменять различные уравнения более сложными процедурами, чем Vensim. Я использую модель со множеством подписчиков, и это создает необычный формат выходных данных. Выходные данные считываются во фрейм данных, индивидуальные значения для подписанных элементов заканчиваются xarray.DataArrays. Мне интересно, как взять столбец xarray.DataArrays (который в конечном итоге является серией) и преобразовать его в двумерный массив со вторым измерением, являющимся числом индексов.
import pysd
import numpy as np
model=pysd.load("Example.py")
stocks=model.run
pop=np.array(Population) #Creates an object array
Population=stocks.Populaton #Creates a series
#How to get an array of population values for each country?
Код example.py выглядит следующим образом (имейте в виду, что это произвольный пример для иллюстрации проблемы)
from __future__ import division
import numpy as np
from pysd import utils
import xarray as xr
from pysd.functions import cache
from pysd import functions
_subscript_dict = {
'Country': ['Canada', 'USA', 'China', 'Norway', 'India', 'England',
'Mexico', 'Yemen']
}
_namespace = {
'TIME': 'time',
'Time': 'time',
'Deaths': 'deaths',
'Births': 'births',
'Population': 'population',
'Birth rate': 'birth_rate',
'Murder rate': 'murder_rate',
'Natural death rate': 'natural_death_rate',
'FINAL TIME': 'final_time',
'INITIAL TIME': 'initial_time',
'SAVEPER': 'saveper',
'TIME STEP': 'time_step'
}
@cache('step')
def deaths():
return murder_rate() * population() + natural_death_rate() * population()
@cache('step')
def births():
return birth_rate() * population()
@cache('step')
def population():
return integ_population()
@cache('run')
def birth_rate():
return utils.xrmerge([
xr.DataArray(
data=[5., 5., 5., 5., 5., 5., 5., 5.],
coords={
'Country':
['Canada', 'USA', 'China', 'Norway', 'India', 'England', 'Mexico', 'Yemen']
},
dims=['Country']),
xr.DataArray(data=[10.], coords={'Country': ['Mexico']}, dims=
['Country']),
xr.DataArray(data=[8.], coords={'Country': ['Yemen']}, dims=
['Country']),
])
@cache('step')
def murder_rate():
return time()
@cache('run')
def natural_death_rate():
return utils.xrmerge([
xr.DataArray(
data=[3., 3., 3., 3., 3., 3., 3., 3.],
coords={
'Country':
['Canada', 'USA', 'China', 'Norway', 'India', 'England', 'Mexico', 'Yemen']
},
dims=['Country']),
xr.DataArray(data=[5.], coords={'Country': ['Yemen']}, dims=['Country']),
xr.DataArray(data=[5.], coords={'Country': ['Mexico']}, dims=['Country']),
])
@cache('run')
def final_time():
return 100
@cache('run')
def initial_time():
return 0
@cache('step')
def saveper():
return time_step()
@cache('run')
def time_step():
return 1
def _init_population():
return xr.DataArray(
data=np.ones([8]) * 10,
coords={
'Country': ['Canada', 'USA', 'China', 'Norway', 'India', 'England', 'Mexico', 'Yemen']
},
dims=['Country'])
@cache('step')
def _dpopulation_dt():
return births() - deaths()
integ_population = functions.Integ(lambda: _dpopulation_dt(), lambda: _init_population())
Приношу свои извинения, если вкладки файла example.py не совпадают. Любая помощь будет оценена!
1 ответ
Спасибо, что поделились примером того, как эти данные выглядят.
Прежде всего, вложенность xarray.DataArray
объекты как скаляры внутри pandas.DataFrame
это весьма нестандартный способ работы с xarray и пандами. Я не рекомендую это. Если каждая запись представляет собой массив данных DataArray, который разделяет (некоторые из них) одни и те же измерения, самый простой способ работы с вашими данными - это xarray.Dataset
Xarray-версия многомерного pandas.DataFrame
,
Тем не менее, должно быть просто преобразовать ваши данные из этого формата в неопубликованные объекты, с которыми легче работать. Лучшее место для начала с Series.values
, который извлекает столбец в виде 1-мерного массива. Затем вы можете перебрать ряд и преобразовать каждый DataArray
в массиве с .values
, тоже. Собираем это вместе:
population_numpy_array = np.stack(
[data_array.values for data_array in df['Population'].values])
Кроме того, вы можете сложить объекты DataArray с помощью xarray. Это сохранит метки, которые облегчат работу с вашими данными:
population_data_array = xr.concat(df['Population'].values, dim='row_name')
Вы можете даже превратить ваш полный объект в xarray.Dataset
для совместного анализа:
ds = xr.Dataset({k: xr.concat(df[k].values, dim='row_name') for k in df.keys()})
(Возможно, именно это и должен делать PySD.)