我的问题与outlined here
非常相似除了我的主数据框有一个类别列,我的权重也是如此:
df
Out[3]:
Symbol var_1 var_2 var_3 var_4 Category
Index
1903 0.000443 0.006928 0.000000 0.012375 A
1904 -0.000690 -0.007873 0.000171 0.014824 A
1905 -0.001354 0.001545 0.000007 -0.008195 C
1906 -0.001578 0.008796 -0.000164 0.015955 D
1907 -0.001578 0.008796 -0.000164 0.015955 A
1909 -0.001354 0.001545 0.000007 -0.008195 B
wgt_df
Out[4]:
Category var_1_wgt var_2_wgt var_3_wgt var_4_wgt
0 A 0.182022 0.182022 0.131243 0.182022
1 B 0.534814 0.534814 0.534814 0.534814
2 C 0.131243 0.534814 0.131243 0.182022
3 D 0.182022 0.151921 0.151921 0.131243
我要做的是为每个类别应用正确的权重以创建新列df ['new_var'],这是加权和。在没有类别的情况下,我可以将权重转换为numpy数组并使用似乎非常快的.dot()
方法。但是,我无法看到如何解决我的问题:如果我在主数据帧上使用groupby()
,df,我必须以某种方式对我的权重数据框wgt_df执行相同的操作。
实际上,df包含数百万行,我需要多次重复这个计算,所以我很想找到一个矢量化解决方案;否则我可以df.groupby('Category')
创建一个数据帧的字典,其关键是类别,例如wgts_dict['A'] = wgts_df[wgts_df.Category == 'A']
,并通过lambda x
应用我的点逻辑,虽然我也不确定如何执行此操作,因为我需要明确引用当前正在处理的哪个组元素才能撤出正确的wgts_df
切片。
答案 0 :(得分:1)
<强>设置强>
print(df)
Out[655]:
var_1 var_2 var_3 var_4 Category
Symbol
1903 0.000443 0.006928 0.000000 0.012375 A
1904 -0.000690 -0.007873 0.000171 0.014824 A
1905 -0.001354 0.001545 0.000007 -0.008195 C
1906 -0.001578 0.008796 -0.000164 0.015955 D
1907 -0.001578 0.008796 -0.000164 0.015955 A
1909 -0.001354 0.001545 0.000007 -0.008195 B
print(w)
Out[656]:
Category var_1_wgt var_2_wgt var_3_wgt var_4_wgt
0 A 0.182022 0.182022 0.131243 0.182022
1 B 0.534814 0.534814 0.534814 0.534814
2 C 0.131243 0.534814 0.131243 0.182022
3 D 0.182022 0.151921 0.151921 0.131243
<强>解决方案强>
#convert Category to numerical encoding
df['C_Number'] = df.Category.apply(lambda x: ord(x.lower())-97)
#Get a dot product for each row with all category weights and the extract the weights by the category number
df['new_var'] = ((df.iloc[:,:4].values).dot(w.iloc[:,-4:].values))[np.arange(len(df)),df.C_Number]
Out[654]:
var_1 var_2 var_3 var_4 Category C_Number new_var
Symbol
1903 0.000443 0.006928 0.000000 0.012375 A 0 0.006038
1904 -0.000690 -0.007873 0.000171 0.014824 A 0 -0.001615
1905 -0.001354 0.001545 0.000007 -0.008195 C 2 -0.000595
1906 -0.001578 0.008796 -0.000164 0.015955 D 3 0.006481
1907 -0.001578 0.008796 -0.000164 0.015955 A 0 0.007300
1909 -0.001354 0.001545 0.000007 -0.008195 B 1 -0.000661
答案 1 :(得分:1)
您可以执行分组(按类别选择),然后执行dot()
,或者您可以执行dot()
,然后按类别进行选择。后者在熊猫中更快更简单。请注意,我使用的数据匹配数据中的列名称和权重框架。
dot()
的代码,然后选择:
df['dot'] = df[df_wgt.columns].dot(df_wgt.T).lookup(df.index, df.Category)
已执行的步骤......
选择要用于df[df_wgt.columns]
这使用了重量数据框中的列标签和排序。这很重要,因为dot()
需要数据的顺序正确。
使用.dot(df_wgt.T)
调整权重会使它们处于.dot()
的正确方向。这样可以计算每行数据的所有权重类别。这意味着在这种情况下,我们所做的乘法数量将是所需数量的四倍,但它仍然可能比分组更快。
使用.lookup(df.index, df.Category)
使用lookup()
我们可以收集该行类别的正确结果。
select(groupby)和dot()
的代码:
def dot(group):
category = group['Category'].iloc[0]
weights = df_wgt.loc[category].values
return pd.Series(
np.dot(group[df_wgt.columns].values, weights), index=group.index)
df['dot'] = df.groupby(['Category']).apply(dot) \
.reset_index().set_index('Index')[0]
测试代码:
import pandas as pd
from io import StringIO
df = pd.read_fwf(StringIO(u"""
Index var_1 var_2 var_3 var_4 Category
1903 0.000443 0.006928 0.000000 0.012375 A
1904 -0.000690 -0.007873 0.000171 0.014824 A
1905 -0.001354 0.001545 0.000007 -0.008195 C
1906 -0.001578 0.008796 -0.000164 0.015955 D
1907 -0.001578 0.008796 -0.000164 0.015955 A
1909 -0.001354 0.001545 0.000007 -0.008195 B"""),
header=1, skiprows=0).set_index(['Index'])
df_wgt = pd.read_fwf(StringIO(u"""
Category var_1 var_2 var_3 var_4
A 0.182022 0.182022 0.131243 0.182022
B 0.534814 0.534814 0.534814 0.534814
C 0.131243 0.534814 0.131243 0.182022
D 0.182022 0.151921 0.151921 0.131243"""),
header=1, skiprows=0).set_index(['Category'])
df['dot'] = df[df_wgt.columns].dot(df_wgt.T).lookup(df.index, df.Category)
print(df)
<强>结果:强>
var_1 var_2 var_3 var_4 Category dot
Index
1903 0.000443 0.006928 0.000000 0.012375 A 0.003594
1904 -0.000690 -0.007873 0.000171 0.014824 A 0.001162
1905 -0.001354 0.001545 0.000007 -0.008195 C -0.000842
1906 -0.001578 0.008796 -0.000164 0.015955 D 0.003118
1907 -0.001578 0.008796 -0.000164 0.015955 A 0.004196
1909 -0.001354 0.001545 0.000007 -0.008195 B -0.004277