【问题标题】:Drop the last row in a group, based on condition根据条件删除组中的最后一行
【发布时间】:2020-02-23 04:32:18
【问题描述】:

我想根据条件删除组中的最后一行。我做了以下事情:

df=pd.read_csv('file')
grp = df.groupby('id')
for idx, i in grp:
   df= df[df['column2'].index[-1] == 'In']

     id     product   date
 0   220    in      2014-09-01 
 1   220    out     2014-09-03 
 2   220    in      2014-10-16
 3   826    in     2014-11-11
 4   826    out     2014-12-09
 5   826    out      2014-05-19
 6   901    in      2014-09-01
 7   901    out     2014-10-05
 8   901    out     2014-11-01

当我这样做时,我会得到: 关键错误:错误

我想要的输出是:

     id     product   date
 0   220    in      2014-09-01 
 1   220    out     2014-09-03
 3   826    in     2014-11-11
 4   826    out     2014-12-09 
 6   901    in      2014-09-01
 7   901    out     2014-10-05

【问题讨论】:

    标签: python pandas dataframe boolean rows


    【解决方案1】:

    如果想删除最后一个in 仅每组链反转掩码与Series.duplicated~ 不等于inSeries.ne

    df = df[~df['id'].duplicated() | df['product'].ne('in')]
    print (df)
        id product        date
    0  220      in  2014-09-01
    1  220     out  2014-09-03
    3  826      in  2014-11-11
    4  826     out  2014-12-09
    5  826     out  2014-05-19
    6  901      in  2014-09-01
    7  901     out  2014-10-05
    8  901     out  2014-11-01
    

    编辑:

    如果希望每个组的所有可能对 in-out 使用 this solution,则只需将非数值 in-out 映射到 dict 的数值,因为 rolling 不适用于字符串:

    #more general solution
    print (df)
         id product        date
    0   220     out  2014-09-03
    1   220     out  2014-09-03
    2   220      in  2014-09-01
    3   220     out  2014-09-03
    4   220      in  2014-10-16
    5   826      in  2014-11-11
    6   826      in  2014-11-11
    7   826     out  2014-12-09
    8   826     out  2014-05-19
    9   901      in  2014-09-01
    10  901     out  2014-10-05
    11  901      in  2014-09-01
    12  901     out  2014-11-01
    

    pat = np.asarray(['in','out'])
    N = len(pat)
    
    d = {'in':0, 'out':1}
    ma  = (df['product'].map(d)
                       .groupby(df['id'])
                       .rolling(window=N , min_periods=N)
                       .apply(lambda x: (x==list(d.values())).all(), raw=False)
                       .mask(lambda x: x == 0) 
                       .bfill(limit=N-1)
                       .fillna(0)
                       .astype(bool)
                       .reset_index(level=0, drop=True)
                 )
    df = df[ma]
    print (df)
         id product        date
    2   220      in  2014-09-01
    3   220     out  2014-09-03
    6   826      in  2014-11-11
    7   826     out  2014-12-09
    9   901      in  2014-09-01
    10  901     out  2014-10-05
    11  901      in  2014-09-01
    12  901     out  2014-11-01
    

    【讨论】:

    • 问题是我需要先遍历每个人(因此是组),然后删除最后一行,如果它没有以“out”结束。因为现在我发现如果它们与上面的行不相似,如何删除该行: df = df.loc [df['profuct'].shift() != df['product']]
    • 我认为我的问题可能只是改变了一点......我如何访问每列“id”中的最后一行,并删除该行,如果列“product”.eq('在')
    • @LouiseMa - 嗯,不明白。主要写你需要删除每个组的最后一个 id,你的预期输出会为每个组生成 in-out 值,现在在评论中需要别的东西。所以现在我很困惑,到底需要什么......
    • hmm sorry... 好的,我尝试输入第二个解决方案,但出现错误:“TypeError: cannot unpack non-iterable int object”
    • @LouiseMa - 好的,我能问点什么吗?你需要每组一对in-out吗?
    【解决方案2】:

    一种简单的方法是在打开 .csv 文件时添加skipfooter=1

    df = pd.read_csv(file, skipfooter=1, engine='python')
    

    【讨论】:

    • @jezrael 我知道你的答案要好得多,这只是为了删除最后一行。
    • max 这只会删除 csv 文件的最后一行,而不是按照上面给出的条件。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-09-06
    • 1970-01-01
    • 2018-03-03
    • 1970-01-01
    相关资源
    最近更新 更多