为了账号安全,请及时绑定邮箱和手机立即绑定

如何过滤将行保留在 Pandas 列中特定单词列表之后的 DataFrame?

如何过滤将行保留在 Pandas 列中特定单词列表之后的 DataFrame?

哆啦的时光机 2023-03-30 10:15:14
如何过滤在按日期排序的特定单词列表之后保留行的数据框?我有一个看起来像的 df    Name    Date    Event   Col10   Sam 1/1/2020    Apple   Test11   Sam 1/2/2020    Apple   Test22   Sam 1/3/2020    BALL    Test13   Sam 1/3/2020    CAT Test24   Sam 1/5/2020    BALL    Test25   Sam 1/6/2020    Apple   Test36   Nick    1/5/2020    CAT Test37   Nick    1/6/2020    BALL    Test38   Nick    1/7/2020    Apple   Test39   Nick    1/8/2020    Apple   Test410  Cat 1/1/2020    Apple   Test111  Cat 1/2/2020    Bat Test2 df=pd.DataFrame({'Name': {0: 'Sam',  1: 'Sam',  2: 'Sam',  3: 'Sam',  4: 'Sam',  5: 'Sam',  6: 'Nick',  7: 'Nick',  8: 'Nick',  9: 'Nick',  10: 'Cat',  11: 'Cat '}, 'Date': {0: '1/1/2020',  1: '1/2/2020',  2: '1/3/2020',  3: '1/3/2020',  4: '1/5/2020',  5: '1/6/2020',  6: '1/5/2020',  7: '1/6/2020',  8: '1/7/2020',  9: '1/8/2020',  10: '1/1/2020',  11: '1/2/2020'}, 'Event': {0: 'Apple',  1: 'Apple',  2: 'BALL',  3: 'CAT',  4: 'BALL',  5: 'Apple',  6: 'CAT',  7: 'BALL',  8: 'Apple',  9: 'Apple',  10: 'Apple',  11: 'Bat'}, 'Col1': {0: 'Test1',  1: 'Test2',  2: 'Test1',  3: 'Test2',  4: 'Test2',  5: 'Test3',  6: 'Test3',  7: 'Test3',  8: 'Test3',  9: 'Test4',  10: 'Test1',  11: 'Test2'}})我想保留在我的活动中发生 BALL 或 CAT 的最早日期之后的行。因此,在我的示例中,我需要消除第 1、2 行和第 11 行,因为我们将 Apple 作为第一个事件。我尝试使用event_filter = ['BALL','CAT']df = df.loc[df['Event'].isin(event_filter)]我还尝试删除基于事件的子集,但它也删除了第 8 行。任何帮助,将不胜感激。我期待的结果是:    Name    Date    Event   Col10   Sam 1/3/2020    BALL    Test11   Sam 1/3/2020    CAT Test22   Sam 1/5/2020    BALL    Test23   Sam 1/6/2020    Apple   Test34   Nick    1/5/2020    CAT Test35   Nick    1/6/2020    BALL    Test36   Nick    1/7/2020    Apple   Test37   Nick    1/8/2020    Apple   Test48   Cat 1/2/2020    Bat Test2
查看完整描述

2 回答

?
临摹微笑

TA贡献1982条经验 获得超2个赞

这样的事情怎么样?另外,好像有错别字。最后一行是 Bat,这应该是 BALL 吗?(根据您的预期输出)


lst = ['CAT', 'BALL']

检查事件中是否存在列表的选定元素。存在则赋1,不存在则赋0。


df['C'] = np.where(df['Event'].isin(lst), 1, 0)

在此之后,我们可以对 C 列执行 cumsum 并过滤行。这可以通过在 Name 上使用 groupby 并在 c 列上执行 cumsum 并检查是否存在大于 0 的 cumsum 来完成。只有当该 groupby (Name) 的事件中存在列表的那些元素时,才会发生大于 0 的情况


df = df.loc[df.groupby('Name')['C'].cumsum()>0].reset_index(drop=True)

df.drop('C', 1, inplace=True)

print (df)


   Name      Date  Event   Col1

0   Sam  1/3/2020   BALL  Test1

1   Sam  1/3/2020    CAT  Test2

2   Sam  1/5/2020   BALL  Test2

3   Sam  1/6/2020  Apple  Test3

4  Nick  1/5/2020    CAT  Test3

5  Nick  1/6/2020   BALL  Test3

6  Nick  1/7/2020  Apple  Test3

7  Nick  1/8/2020  Apple  Test4


查看完整回答
反对 回复 2023-03-30
?
慕勒3428872

TA贡献1848条经验 获得超6个赞

这有点难以理解(您是否将事件过滤器从 Bat 切换为 BALL?:D),而且您似乎正在尝试让每个人获得第一个事件?


如果是这样,我认为您需要按名称拆分数据框,根据需要进行过滤,然后重新组合。


这是第一次出现的小函数:


def get_min_index(ser, event_filter):


    in_event = ser.isin(event_filter)

    return in_event.loc[in_event].index[0]

然后假设您的 df 已经按照您的需要进行了排序。


tdf_lst = []

names = df['Name'].unique()


for name in names:


    tdf = df.loc[df['Name']==name, :] # filter for the individual name

    min_idx = get_min_index(tdf['Event'], event_filter) # get the first index

    tdf = tdf.loc[min_idx:,:] # select from the first index to the last

    tdf_lst.append(tdf)

    

df_fltrd = pd.concat(tdf_lst)

也许有一个更优雅的解决方案,但希望这就是您正在寻找的


查看完整回答
反对 回复 2023-03-30
  • 2 回答
  • 0 关注
  • 99 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信