Поэтому я думаю, что проблема заключается в том, что вы рассматриваете свои данные как по существу трехмерные, где у вас есть измерения (фирмы, компоненты затрат, компоненты дохода), и вы хотите, чтобы коэффициенты для каждого внешнего продукта трехразмеры.
Конечно, есть способы выполнить то, что вы хотели бы сделать в DataFrame, но они беспорядочные.
У Pandas есть трехмерный объект, называемый Panel, но это устарело в пользу более полного решения для индексированных структур данных с большими измерениями, которое называется xarray .Думайте об этом как о пандах для NDArrays.
Мы можем преобразовать ваши данные в xarray DataArray, пометив и сложив ваши индексы:
In [2]: income = df1.set_index('firms').rename_axis(['income'], axis=1).stack('income').to_xarray()
In [3]: income
Out[3]:
<xarray.DataArray (firms: 3, income: 2)>
array([[150, 200],
[200, 210],
[ 50, 90]])
Coordinates:
* firms (firms) object '1' '2' '3'
* income (income) object 'Sales' 'Profit'
In [4]: costs = df2.set_index('firms').rename_axis(['costs'], axis=1).stack('costs').to_xarray()
In [5]: costs
Out[5]:
<xarray.DataArray (firms: 3, costs: 2)>
array([[10000, 2],
[20000, 4],
[ 500, 5]])
Coordinates:
* firms (firms) object '1' '2' '3'
* costs (costs) object 'Salary' 'employees'
Теперь у вас есть два DataArrays, каждый с двумя измерениями,но размеры не совпадают.Оба индекса индексируются firms
, но доход индексируется income
, а затраты индексируются costs
.
Это , передаваемые друг против друга автоматически, когда операции выполняются с обоимииз них:
In [6]: income / costs
Out[6]:
<xarray.DataArray (firms: 3, income: 2, costs: 2)>
array([[[1.50e-02, 7.50e+01],
[2.00e-02, 1.00e+02]],
[[1.00e-02, 5.00e+01],
[1.05e-02, 5.25e+01]],
[[1.00e-01, 1.00e+01],
[1.80e-01, 1.80e+01]]])
Coordinates:
* firms (firms) object '1' '2' '3'
* income (income) object 'Sales' 'Profit'
* costs (costs) object 'Salary' 'employees'
Эти данные теперь имеют структуру, которую вы пытаетесь достичь, и это деление было выполнено с использованием оптимизированных операций Cython, а не циклов.
Вы можете преобразовать данные обратнок кадру данных, используя встроенный метод DataArray.to_series
:
In [7]: (income / costs).to_series().to_frame(name='income to cost ratio')
Out[7]:
income to cost ratio
firms income costs
1 Sales Salary 0.0150
employees 75.0000
Profit Salary 0.0200
employees 100.0000
2 Sales Salary 0.0100
employees 50.0000
Profit Salary 0.0105
employees 52.5000
3 Sales Salary 0.1000
employees 10.0000
Profit Salary 0.1800
employees 18.0000