import numpy as np
import pandas as pd
df1 = pd.DataFrame({"id": ["s1", "s2", "s3"],"threshold": [1, 2, 7]})
df2 = pd.DataFrame({"id": ["s1", "s1", "s1", "s2", "s2", "s3", "s3", "s3", "s5", "s5"], "value": [2, -1, 1, -3, 3, 3, 4, 2, 1, 6]})
我想在数据框df1中添加一列,以便:
例如
我知道我也可以通过循环处理此计算。
即
df1['my_stat_column'] = 0 # initialize
for i in range(0, df1.shape[0]):
s = df1.iloc[i]['id']
t = df1.iloc[i]['threshold']
for v in range(0, df2.shape[0]):
non_pythonic_and_stupid_way = df2[ (df2['id']==s) & (df2['value']>=t)]
my_stat_value = non_pythonic_and_stupid_way['value'].sum()
df1.iloc[i]['my_stat_column'] = my_stat
df1.head()
那么,通过另一数据框的列过滤一个熊猫数据框的真正方法是什么?
谢谢!
答案 0 :(得分:1)
在您的帖子中,df1.threshold
和df2.value
均应为数字:
df2.value = pd.to_numeric(df2.value)
df1.threshold = pd.to_numeric(df1.threshold)
由于我们正在使用对齐的id
,因此最好将它们编入索引:
df1.set_index('id', inplace=True)
df2.set_index('id', inplace=True)
然后,df1.id
仅应具有唯一值,因此,我们可以首先标记所有大于或等于阈值的值:
df2['valid'] = df2.value.ge(df1.threshold)
df2['valid'] = df2.value * df2['valid']
然后您可以进行简单的分组:
df1['newcolumn'] = df2.groupby('id').valid.sum()
输出:
threshold newcolumn
id
s1 1 3
s2 2 3
s3 7 0
选项2:,您可以使用id
(将列转换为数字后),而不用将merger
设置为索引:
new_df = df2.merge(df1, on='id', how='outer')
# similar to above, in one step
new_df['valid'] = new_df.value.ge(new_df.threshold) * new_df.value
# then groupby:
new_df.groupby('id').valid.sum()
给予:
id
s1 3
s2 3
s3 0
s5 0
Name: valid, dtype: int64
答案 1 :(得分:0)
如果您正在寻找较短的代码,这是我的答案
df1['my_stat_column'] = [df2[df2.id == i][df2[df2.id == i].value >= t].value.sum() for _,i,t in df1.itertuples()]
我认为没有一种“真正的”方法可以在python中做任何事情。有很多方法,您需要根据应用程序找到最有效的方法或最易读的方法等。