尝试实现一个简单的func,将一个组标记为True
,随机
数据帧:
In [145]: df = pd.DataFrame({'a': [1,1,1,2,2], 'b': [3,3,3,3,3]})
In [146]: df
Out[146]:
a b
0 1 3
1 1 3
2 1 3
3 2 3
4 2 3
功能:
def pickone(df, group, out):
u = df[group].unique()
p = np.random.choice(u, 1)[0]
df[out] = False
df[df[group]==p][out] = True
return df
应用它可以在分组数据帧上正常工作:
In [148]: df.groupby(['b']).apply(pickone, group="a", out="c")
Out[148]:
a b c
0 1 3 True
1 1 3 True
2 1 3 True
3 2 3 False
4 2 3 False
但不适用于未分组的dfs :
In [149]: df.apply(pickone, group="a", out="c")
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
pandas/_libs/index.pyx in pandas._libs.index.IndexEngine.get_loc (pandas/_libs/index.c:5085)()
pandas/_libs/hashtable_class_helper.pxi in pandas._libs.hashtable.Int64HashTable.get_item (pandas/_libs/hashtable.c:13892)()
TypeError: an integer is required
During handling of the above exception, another exception occurred:
KeyError Traceback (most recent call last)
<ipython-input-149-86c0d6e0e423> in <module>()
----> 1 df.apply(pickone, group="a", out="c")
答案 0 :(得分:2)
df
是一个DataFrame,而df.groupby(...)
是DataFrameGroupBy
个对象。
DataFrame.apply
和DataFrameGroupBy.apply
是两种完全不同的方法。
df.apply
用于为每行(默认情况下)或每列调用一次函数。
该函数需要一个Series(一行或一列)作为它的第一个参数。
df.groupby(...).apply
用于每组调用一次函数。
该函数需要一个(子)DataFrame作为它的第一个参数。
要在pickone
上致电df
,请使用
pickone(df, group='a', out='c')
而不是df.apply(pickone, ...)
。
顺便说一下,
df[df[group]==p][out] = True
是使用链式索引的分配。因为,对于某些DataFrame,df[df[group]==p]
可能会返回包含从df
复制的数据的新DataFrame,df[df[group]==p][out] = True
可能会修改新的DataFrame而非df
本身。
因此,链式索引的分配是considered a no-no。而是使用df.loc
:
df[out] = False
df.loc[df[group]==p, out] = True
或者,在这种情况下,
df[out] = (df[group]==p)
就足够了。