我有一个数据集,我想添加一列来表示某些计算的结果(它复杂)需要在每个组中完成计算,每个行值依赖于它上面的行。这是我到目前为止的代码和所需输出的简单示例:
修改1 所以我在下面更新了我的代码,也许我不理解apply如何工作,但我认为这会执行两次(每组一次)。然后,我的函数将遍历这些执行中的每一行。我仍然感到困惑的是为什么它要去3次......我想"被执行"会打印5次。对此的想法?
编辑2 我的返回功能上的缩进错了。修好了。谢谢你的帮助!
import pandas as pd
df = pd.DataFrame({'type' : ['foo', 'foo', 'foo', 'bar','bar'], 'cost' : [1, 4, 2, 8,9]})
df['class'] = np.nan
def customFunction(test_df):
print np.shape(test_df)
iteration = 1
for currRow in test_df.iterrows():
print 'executed'
if iteration == 1:
test_df['class'] = 'first'
else:
if currRow[1]['cost'] > priorCost:
test_df['class'] = 'greater'
elif currRow[1]['cost'] < priorCost:
test_df['class'] = 'less'
else:
test_df['class'] = 'equal'
iteration += 1
priorCost = currRow[1]['cost']
return test_df
grouped_df = df.groupby(['type']).apply(customFunction)
输出:
(2, 2)
executed
(2, 2)
executed
(3, 2)
executed
cost type class
0 1 foo first
1 4 foo first
2 2 foo first
3 8 bar first
4 9 bar first
答案 0 :(得分:2)
到目前为止,我会给你 - 我现在需要休息一下,但是:
df = pd.DataFrame(pd.read_clipboard())
df.set_index('type', inplace=True)
test = df.groupby(level=0).apply(lambda x: x.cost.diff())
给我(因为diff()
计算列w.r.t.第一个条目内的差异)
Out[160]:
type
bar type
bar NaN
bar 1
Name: cost, dtype: ...
foo type
foo NaN
foo 3
foo -2
Name: co...
dtype: object
因此,这包含您需要的所有信息。目前,我正在努力将这些信息合并回原始数据帧。 df['differences'] = test
造成了巨大的混乱。
<强>更新强>
我快到了:
>>> df['differences'] = test[1].append(test[0])
>>> df.loc[df['differences'] > 0, 'inWords'] = 'greater'
>>> df.loc[df['differences'] < 0, 'inWords'] = 'lesser'
>>> df.loc[df['differences'].isnull(), 'inWords'] = 'first'
>>> df
Out[184]:
cost differences inWords
type
foo 1 NaN first
foo 4 3 greater
foo 2 -2 lesser
bar 8 NaN first
bar 9 1 greater
因此,唯一需要的是通用表达式而不是test[1].append(test[0])
。也许其他人可以在这里筹码?
更新2
回复您的评论:每当您为apply()
定义功能时,
def compareSomethingWithinAGroup(group):
someMagicHappens()
return someValues
您可以访问所有标准pandas功能以及功能内的整个组。那么,你可以创建所有复杂的行依赖魔法,无论它是什么。您唯一需要注意的事项是:someValues
必须是Series
或dataframe
,只有一列,其中包含的行数与group
的行数相同。只要您返回此类someValues
,您就可以随时df['resultOfSomethingComplicated'] = df.groupby(level=0).apply(compareSomethingWithinAGroup)
,并使用回复中的所有行。