我需要将数据帧拆分成组,对于那些具有奇数行的组,我需要拉入其列匹配某个条件的第一行,然后我需要汇回所有这些第一行(所以只有符合条件的奇数组中的第一个)。我可以在下面的循环(它工作)中执行它,但不能使用apply将其重新编写为groupby。你能帮忙吗?
grp_by_cols=['A','B']
new_df=pd.DataFrame(columns=grp_by_cols)
for name, group in txn.groupby(grp_by_cols):
if len(group) % 2 != 0:
new_df=new_df.append(group[group['C']=='something')].head(1))
答案 0 :(得分:2)
有趣的问题,我会通过编写一个函数然后通过申请来解决。
假设您有这样的数据(对问题很方便):
import pandas as pd
import random
DF = pd.DataFrame({
'key' : [1, 1, 1, 2, 2, 3, 3, 3, 4, 4, 5, 5, 5, 6, 6, 7, 7, 7],
'data1' : ['A', 'B', 'C', 'A', 'B', 'B', 'B', 'C', 'A', 'B', 'A', 'B', 'C',
'A', 'B', 'B', 'B', 'C'],
'data2' : [random.random() for x in xrange(18)]})
其中key是您要分组的列," data1'是您将用于测试条件的列。对于组1,3,5和7,该数据具有奇数个观察结果。<数据1'第一次观察时这些群体的价值是A' B' B' A'' B'例如,假设您希望获得一个新数据框,其中包含这些组中的第一个观察结果,但仅限于“数据1”和“数据”的位置。第一行中的值等于B.我们可以写一个像这样的通用函数:
def apply_func(df, col, condition):
if len(df)%2 == 0:
return None
else:
if df.irow(0)[col] == condition:
return df.irow(0)
else:
return None
然后按如下方式在组上调用它:
DF.groupby('key').apply(apply_func, 'data1', 'B').dropna()
给出以下输出:
data1 data2 key
2 B 0.980814 3
6 B 0.428402 7
如果我没弄错的话,那就是你想要生成的输出类型。
当然你实际上并不需要函数中的所有分支,我只是为了让它更清晰。编写函数最简洁的方法是:
def apply_func(df, col, condition):
if len(df)%2 != 0 and df.irow(0)[col] == condition:
return df.irow(0)
请注意,在调用传递要应用的函数时,传递的第一个参数是DataFrame本身,这是自动完成的。这就是为什么你不需要指定' df'传递函数以应用时的参数。事实上,如果你这样做,你会得到一个错误,说你已经传递了太多的论据。在我的视图中,在传递函数时,有点奇怪的是,参数是在逗号之后而不是在括号中提供的。我觉得这看起来令人困惑,但它就是它......