2016-05-13 44 views
1

我正在用python熊猫与groupby挣扎。我应该如何完成以下任务?对于每一个水果,我想找出与那个水果的“第0步”值不同的地方。Python熊猫groupby与其他行的差别按列过滤

df = pd.DataFrame({'Fruit' : ['Apple', 'Apple', 'Apple', 'Banana', 'Banana', 'Banana'], 'Step' : [0, 1, 2, 0, 1, 2], 'Value' : [100, 102, 105, 200, 210, 195] }) 

    Fruit Step Value  to-be 
0 Apple  0 100 --> 0 
1 Apple  1 102 --> 2 
2 Apple  2 105 --> 5 
3 Banana  0 200 --> 0 
4 Banana  1 210 --> 10 
5 Banana  2 195 --> -5 

谢谢!

回答

5

这应做到:

df.groupby('Fruit').apply(lambda g: g.Value - g[g.Step == 0].Value.values[0]) 

首先,我们被你关心(水果)列分组。然后,我们对每个组应用一个函数(使用lambda,它可以让我们指定一个函数内联)。对于每个组,我们找到其中的行(g.Step == 0),然后从该行获取Value条目,并使用values[0]获取第一个值(如果存在多个地方,则为g.Step == 0)。然后我们从组中的所有行中减去一个值,然后返回它。

如果你想将其添加为数据帧一列,你可以删除索引:

res = df.groupby('Fruit').apply(lambda g: g.Value - g[g.Step == 0].Value.values[0]) 
df['Result'] = res.reset_index(drop=True) 
+0

此行'DF [ '结果'] = res.reset_index( drop = True)'对我来说''ValueError:传递的项目数量错误1,索引暗示3''对我来说不适用' – SparkAndShine

+0

@sparkandshine这很奇怪。你使用的是什么版本的Python?这对我2.7.3运行良好。 – ASGM

+0

我的Python版本是'2.7.6'。 – SparkAndShine

1

觉得这样做的伎俩。它只是遍历行并在每次步数等于0时应用新的“第一个”值。然后计算与第一个值的差值。

rows = range(df.shape[0]) 
df['count'] = 0 
for r in rows: 
    step = df.iloc[r,1] 
    value = df.iloc[r,2] 
    if step == 0: 
     first = value 
    df.iloc[r,3] = value - first 
+0

这绝对有效,但在较大的数据框中,它将比分组慢。一般来说,遍历单行不能充分利用熊猫所提供的功能。 (我提到这不是为了攻击你的答案,而是因为当我开始学习熊猫时,有人给了我同样的建议,这真的很有帮助)。 – ASGM

+0

我完全同意,你的答案在这里肯定比较强。然而,我有时会想(特别是因为这似乎是初学者),一些简单的事情可以在更简单的情况下进行,并且更容易加入。当我开始时,我发现'lambda'很难让我头脑发热! – EllieFev

+0

非常真实!看到做事有多种方式总是很有用(我敢肯定有一种比我投入的方法更好的方法)。 – ASGM

1

我是熊猫的新手,但至少下面的代码工作。结果的末尾,

Fruit Step Value to-be 
0 Apple  0 100  0 
1 Apple  1 102  2 
2 Apple  2 105  5 
3 Banana  0 200  0 
4 Banana  1 210  10 
5 Banana  2 195  -5 

[6 rows x 4 columns] 

源代码如下。

import pandas as pd 

df = pd.DataFrame({'Fruit' : ['Apple', 'Apple', 'Apple', 'Banana', 'Banana', 'Banana'], 
        'Step' : [0, 1, 2, 0, 1, 2], 
        'Value' : [100, 102, 105, 200, 210, 195] }) 

list_groups = list() 

# loop over dataframe groupby `Fruit` 
for name, group in df.groupby('Fruit'): 
    group.sort('Step', ascending=True) # sorted by `Step` 

    row_iterator = group.iterrows() 

    # get the base value 
    idx, first_row = row_iterator.next() 
    base_value = first_row['Value'] 

    to_be = [0] # store the values of the column `to-be` 
    for idx, row in row_iterator: 
     to_be.append(row['Value'] - base_value) 

    # add a column to group 
    group['to-be'] = pd.Series(to_be, index=group.index) 

    list_groups.append(group) 


# Concatenate dataframes 
result = pd.concat(list_groups) 

print(result) 

@ASGM,我跑你的代码,

res = df.groupby('Fruit').apply(lambda g: g.Value - g[g.Step == 0].Value.values[0]) 
df['Result'] = res.reset_index(drop=True) 

,但遇到问题,

Traceback (most recent call last): 
    File "***.py", line 9, in <module> 
    df['Result'] = res.reset_index(drop=True) 
    File "/usr/lib/python2.7/dist-packages/pandas/core/frame.py", line 1887, in __setitem__ 
    self._set_item(key, value) 
    File "/usr/lib/python2.7/dist-packages/pandas/core/frame.py", line 1968, in _set_item 
    NDFrame._set_item(self, key, value) 
    File "/usr/lib/python2.7/dist-packages/pandas/core/generic.py", line 1068, in _set_item 
    self._data.set(key, value) 
    File "/usr/lib/python2.7/dist-packages/pandas/core/internals.py", line 3024, in set 
    self.insert(len(self.items), item, value) 
    File "/usr/lib/python2.7/dist-packages/pandas/core/internals.py", line 3039, in insert 
    self._add_new_block(item, value, loc=loc) 
    File "/usr/lib/python2.7/dist-packages/pandas/core/internals.py", line 3162, in _add_new_block 
    self.items, fastpath=True) 
    File "/usr/lib/python2.7/dist-packages/pandas/core/internals.py", line 1993, in make_block 
    placement=placement) 
    File "/usr/lib/python2.7/dist-packages/pandas/core/internals.py", line 64, in __init__ 
    '%d' % (len(items), len(values))) 
ValueError: Wrong number of items passed 1, indices imply 3 
[Finished in 0.4s with exit code 1]