繁体   English   中英

在Python中将一个df中的每一列划分为另一个df中的每一列

[英]Divide every column in one df to every column in another df in Python

美好的一天,

问题:我有两个数据框-每个公司的绩效又称为每个公司的输出和输入:

`firms = ['1', '2', '3']
df = pd.DataFrame(firms)
output = { 'firms': ['1', '2', '3'],
'Sales': [150, 200, 50],
'Profit':[200, 210, 90]}
df1 = pd.DataFrame.from_dict(output)
inputs = { 'firms': ['1', '2', '3'],
'Salary': [10000, 20000, 500],
'employees':[2, 4, 5]}
df2 = pd.DataFrame.from_dict(inputs)`

我需要的是将输出表中的每一列划分为输入表中的每一列。 到目前为止,我正在以非常丑陋的方式进行操作-将整个输出tbl除以输入表中的每个单独列,然后将结果合并在一起。 当我有两列时,这一切都很好,但是我想知道是否有更好的方法,因为我可能在一个表中有100列,而在另一个表中有50列。 嗯,大小可能有所不同也很重要,例如,输入中的50 cols和输出表中的100 cols。

frst = df1.iloc[:,0:2].divide(df2.Salary, axis = 0)
frst.columns = ['y1-x1', 'y2-x1']
sec = df1.iloc[:,0:2].divide(df2.employees, axis = 0)
sec.columns = ['y1-x2', 'y2-x2']
complete = pd.DataFrame(df).join(frst).join(sec)

输出:

| 公司 y1-x1 | y2-x1 | y1-x2 | y2-x2 |

| 1 | 0.0200 | 0.015 | 100.0 | 75.0 |

| 2 | 0.0105 | 0.010 | 52.5 | 50.0 |

| 3 | 0.1800 | 0.100 | 18.0 | 10.0 |

我也尝试过使用循环,但是如果我没有记错的话,因为在我的实际示例中,我有不同大小的表,因此无法解决问题。 我将非常感谢您的建议!

因此,我认为问题在于,您实际上将数据视为三维的,具有维度(公司,成本成分,收入成分),并且您希望三个维度的每个外部乘积都具有比率。

当然,有多种方法可以完成您想要在DataFrame中完成的工作,但是它们很混乱。

熊猫确实有一个称为Panel的3-D对象,但是不建议使用此方法 ,而是希望为称为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'

现在,您有两个DataArray,每个DataArray具有两个维度,但是维度不匹配。 两者均由firms索引,但收入由income索引, costscosts索引。

当对两者执行操作时,它们会自动相互广播

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方法将数据转换回数据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

我不明白为什么你不能只使用一个简单的循环。 似乎您想使firms所有内容保持一致,因此将其设置为索引将解决长度不相等的所有联接或除法。

df1 = df1.set_index('firms')
df2 = df2.set_index('firms')

l = []
for col in df2.columns:
    l.append(df1.div(df2[col], axis=0).add_suffix(f'_by_{col}'))
pd.concat(l, axis=1)

输出:

       Sales_by_Salary  Profit_by_Salary  Sales_by_employees  Profit_by_employees
firms                                                                            
1                0.015            0.0200                75.0                100.0
2                0.010            0.0105                50.0                 52.5
3                0.100            0.1800                10.0                 18.0

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM