根据多索引名称将 DataFrame 单元格中的每个值相乘
Multiply each value in DataFrame cell according to multi-index name
鉴于此 pandas 数据框
list_index = pd.Series(['A' for i in range(2)] + ['B' for i in range(4)] + ['C' for i in range(3)] + ['D' for i in range(6)], name='indexes')
list_type = pd.Series(['a', 'c'] + ['a', 'b','c','d'] + ['f','g','i'] + ['a','c','d','e','f','g'], name='types')
df = pd.DataFrame({
'value' : [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
}, index=[list_index, list_type])
indexes types value
A a 1
c 2
B a 3
b 4
c 5
d 6
C f 7
g 8
i 9
D a 10
c 11
d 12
e 13
f 14
g 15
我想将每个值乘以另一个 pandas.Dataframe
中包含的一个因子(即比率)
ratio_df = pd.DataFrame({
'ratio' : [0.1, 0.2, 0.4, 0.5]
}, index=['A', 'B', 'C', 'D'])
ratio
A 0.1
B 0.2
C 0.4
D 0.5
因此 df
中所有 'indexes' == 'A' 的值都乘以 0.1,'indexes' == 'B' 的值乘以 0.1以 0.2 依此类推。
我确信有一些聪明的方法可以做到这一点,但现在我真的想不出。我知道我可以 'expand' ratio_df 到相同长度的 df (使用 reset_index() 然后为 df 创建一个包含比率的新列)而不是简单地执行 *
操作成对,但我不确定这是最快的方法。
我也看过这个 但它与我的情况略有不同。
这是一种只重置第一级的方法; join
ing; multiply
ing 和 set_index
回到原来的:
out = df.reset_index(level=1).join(ratio_df).assign(New=lambda x: x['value']*x['ratio']).set_index('types', append=True)
输出:
value ratio New
types
A a 1 0.1 0.1
c 2 0.1 0.2
B a 3 0.2 0.6
b 4 0.2 0.8
c 5 0.2 1.0
d 6 0.2 1.2
C f 7 0.4 2.8
g 8 0.4 3.2
i 9 0.4 3.6
D a 10 0.5 5.0
c 11 0.5 5.5
d 12 0.5 6.0
e 13 0.5 6.5
f 14 0.5 7.0
g 15 0.5 7.5
将 ratio
列重命名为 value
然后在 level=0
上使用 mul
:
df.mul(ratio_df.rename(columns={'ratio': 'value'}), level=0)
结果
value
indexes types
A a 0.1
c 0.2
B a 0.6
b 0.8
c 1.0
d 1.2
C f 2.8
g 3.2
i 3.6
D a 5.0
c 5.5
d 6.0
e 6.5
f 7.0
g 7.5
如果只是需要两列的乘积Series.mul可以根据索引级别对齐
仅 select 列和 mul
索引级别:
df['value'].mul(ratio_df['ratio'], level='indexes')
或索引级别编号:
df['value'].mul(ratio_df['ratio'], level=0)
结果是一个未命名的系列:
indexes types
A a 0.1
c 0.2
B a 0.6
b 0.8
c 1.0
d 1.2
C f 2.8
g 3.2
i 3.6
D a 5.0
c 5.5
d 6.0
e 6.5
f 7.0
g 7.5
dtype: float64
结果系列可以根据需要分配回df
:
df['new'] = df['value'].mul(ratio_df['ratio'], level='indexes')
df
:
value new
indexes types
A a 1 0.1
c 2 0.2
B a 3 0.6
b 4 0.8
c 5 1.0
d 6 1.2
C f 7 2.8
g 8 3.2
i 9 3.6
D a 10 5.0
c 11 5.5
d 12 6.0
e 13 6.5
f 14 7.0
g 15 7.5
鉴于此 pandas 数据框
list_index = pd.Series(['A' for i in range(2)] + ['B' for i in range(4)] + ['C' for i in range(3)] + ['D' for i in range(6)], name='indexes')
list_type = pd.Series(['a', 'c'] + ['a', 'b','c','d'] + ['f','g','i'] + ['a','c','d','e','f','g'], name='types')
df = pd.DataFrame({
'value' : [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
}, index=[list_index, list_type])
indexes types value
A a 1
c 2
B a 3
b 4
c 5
d 6
C f 7
g 8
i 9
D a 10
c 11
d 12
e 13
f 14
g 15
我想将每个值乘以另一个 pandas.Dataframe
中包含的一个因子(即比率)ratio_df = pd.DataFrame({
'ratio' : [0.1, 0.2, 0.4, 0.5]
}, index=['A', 'B', 'C', 'D'])
ratio
A 0.1
B 0.2
C 0.4
D 0.5
因此 df
中所有 'indexes' == 'A' 的值都乘以 0.1,'indexes' == 'B' 的值乘以 0.1以 0.2 依此类推。
我确信有一些聪明的方法可以做到这一点,但现在我真的想不出。我知道我可以 'expand' ratio_df 到相同长度的 df (使用 reset_index() 然后为 df 创建一个包含比率的新列)而不是简单地执行 *
操作成对,但我不确定这是最快的方法。
我也看过这个
这是一种只重置第一级的方法; join
ing; multiply
ing 和 set_index
回到原来的:
out = df.reset_index(level=1).join(ratio_df).assign(New=lambda x: x['value']*x['ratio']).set_index('types', append=True)
输出:
value ratio New
types
A a 1 0.1 0.1
c 2 0.1 0.2
B a 3 0.2 0.6
b 4 0.2 0.8
c 5 0.2 1.0
d 6 0.2 1.2
C f 7 0.4 2.8
g 8 0.4 3.2
i 9 0.4 3.6
D a 10 0.5 5.0
c 11 0.5 5.5
d 12 0.5 6.0
e 13 0.5 6.5
f 14 0.5 7.0
g 15 0.5 7.5
将 ratio
列重命名为 value
然后在 level=0
上使用 mul
:
df.mul(ratio_df.rename(columns={'ratio': 'value'}), level=0)
结果
value
indexes types
A a 0.1
c 0.2
B a 0.6
b 0.8
c 1.0
d 1.2
C f 2.8
g 3.2
i 3.6
D a 5.0
c 5.5
d 6.0
e 6.5
f 7.0
g 7.5
如果只是需要两列的乘积Series.mul可以根据索引级别对齐
仅 select 列和 mul
索引级别:
df['value'].mul(ratio_df['ratio'], level='indexes')
或索引级别编号:
df['value'].mul(ratio_df['ratio'], level=0)
结果是一个未命名的系列:
indexes types
A a 0.1
c 0.2
B a 0.6
b 0.8
c 1.0
d 1.2
C f 2.8
g 3.2
i 3.6
D a 5.0
c 5.5
d 6.0
e 6.5
f 7.0
g 7.5
dtype: float64
结果系列可以根据需要分配回df
:
df['new'] = df['value'].mul(ratio_df['ratio'], level='indexes')
df
:
value new
indexes types
A a 1 0.1
c 2 0.2
B a 3 0.6
b 4 0.8
c 5 1.0
d 6 1.2
C f 7 2.8
g 8 3.2
i 9 3.6
D a 10 5.0
c 11 5.5
d 12 6.0
e 13 6.5
f 14 7.0
g 15 7.5