借助另一数据框的列来过滤一个熊猫数据框的理想方法是什么?

时间:2019-06-17 12:05:11

标签: python pandas dataframe

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 [“ newcolumn”]是df2中“值”的“和”,
  • 对于df1中的相应ID
  • df2中的“值”大于或等于df1中定义的“阈值”
  • 每个ID。

例如

  • 对于df1中的id =“ s1”,
  • df2中有三个“值”(即2,-1和1),
  • 在df2中的这些“值”中,只有2和1大于或等于在df1中为s1定义的“阈值”(即1)
  • 因此,代码应返回s1的2 + 1 = 3,
  • 以类似的方式,它应为s2返回3,
  • 以类似的方式,它应为s3返回0,
  • 以类似的方式,它应该返回,大概是s5的NaN

我知道我也可以通过循环处理此计算。

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()

那么,通过另一数据框的列过滤一个熊猫数据框的真正方法是什么?

谢谢!

2 个答案:

答案 0 :(得分:1)

在您的帖子中,df1.thresholddf2.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中做任何事情。有很多方法,您需要根据应用程序找到最有效的方法或最易读的方法等。