【问题标题】:Python Pandas: Eliminate a row from a dataframe if a value in a any preceding row in a groupby meets a certain criteriaPython Pandas:如果 groupby 中任何前一行中的值满足特定条件,则从数据框中删除一行
【发布时间】:2015-01-10 17:58:00
【问题描述】:

一旦周变得不连续超过 1,我就会尝试从 groupby 中删除数据。即,如果一周内有间隔,那么我想删除该行和该 group by 中的后续行。下面是我拥有的数据结构的一个简单示例,也是我正在寻找的理想输出。数据需要按国家和产品分组。

import pandas as pd

data = {'Country' : ['US','US','US','US','US','DE','DE','DE','DE','DE'],'Product' :         ['Coke','Coke','Coke','Coke','Coke','Apple','Apple','Apple','Apple','Apple'],'Week' : [1,2,3,4,6,1,2,3,5,6] }

df = pd.DataFrame(data)

print df

#Current starting Dataframe.
  Country Product  Week
0      US    Coke     1
1      US    Coke     2
2      US    Coke     3
3      US    Coke     4
4      US    Coke     6
5      DE   Apple     1
6      DE   Apple     2
7      DE   Apple     3
8      DE   Apple     5
9      DE   Apple     6

#Ideal Output below:
  Country Product  Week
0      US    Coke     1
1      US    Coke     2
2      US    Coke     3
3      US    Coke     4
5      DE   Apple     1
6      DE   Apple     2
7      DE   Apple     3

因此输出删除了美国可口可乐的第 6 周,因为前一周是第 4 周。 对于 DE Apple 第 5 周和第 6 周被删除,因为前一周到第 5 周是 3。请注意,这也消除了 DE Apple 第 6 周,即使它的前一个是 5 或 diff() 为 1。

【问题讨论】:

    标签: python pandas row slice


    【解决方案1】:

    这应该可行

    df.groupby(['Country', 'Product']).apply(lambda sdf: sdf[(sdf.Week.diff(1).fillna(1) != 1).astype('int').cumsum() == 0]).reset_index(drop=True)
    

    另一种可能更具可读性的方法(即生成一组连续周并检查观察到的周)

    df['expected_week'] = df.groupby(['Country', 'Product']).Week.transform(lambda s: range(s.min(), s.min() + s.size))
    df[df.Week == df.expected_week]
    

    【讨论】:

    • 谢谢,它成功降低了 US Coke 6 和 DE Apple 5。但 DE Apple 6 仍然存在。
    • 感谢第一个现在可以工作,但是如果我将 .cumsum() == 1 更改为 .cumsum() != 1]) 它会产生相反的效果,它是完美的。第二个我喜欢这个逻辑,它更容易让我理解添加一个额外的列,但我收到了一些奇怪的错误消息。“TypeError: incompatible index of inserted column with frame index”感谢您的所有输入。
    【解决方案2】:

    你可以试试这个方法...

    def eliminate(x):
        x['g'] = x['Week'] - np.arange(x.shape[0])
        x = x[x['g'] == x['g'].min()]
        x = x.drop('g',1)
    
        return x
    
    out  = df.groupby('Product').apply(eliminate).reset_index(level=0,drop=True)
    

    【讨论】:

    • 感谢@ZJS,这让我很好地了解了使用函数而不是 lambda,lamdas 仍然让我感到困惑。当我运行你的代码时,它看起来不错,除了它似乎也放弃了美国可口可乐第 4 周,我需要维护它,因为它仍然与前一周保持一致。
    猜你喜欢
    • 1970-01-01
    • 2021-12-26
    • 1970-01-01
    • 1970-01-01
    • 2022-01-13
    • 1970-01-01
    • 2015-10-13
    • 1970-01-01
    • 2013-03-23
    相关资源
    最近更新 更多