【问题标题】:Returning subset of each group from a pandas groupby object从 pandas groupby 对象返回每个组的子集
【发布时间】:2015-11-03 17:20:05
【问题描述】:

我有一个看起来像这样的多级数据框:

                      date_time      name  note   value
list index                                    
1    0     2015-05-22 05:37:59       Tom   129    False
     1     2015-05-22 05:38:59       Tom     0    True
     2     2015-05-22 05:39:59       Tom     0    False
     3     2015-05-22 05:40:59       Tom    45    True
2    4     2015-05-22 05:37:59       Kate   129    True
     5     2015-05-22 05:41:59       Kate     0    False
     5     2015-05-22 05:37:59       Kate     0    True

我想遍历list,并为list 的每一行检查value 列的值,如果是False,则删除该行。所以最终的目标是删除list中的所有第一行,在value中有False 我使用这段代码,这似乎是逻辑:

def delete_first_false():
    for list, new_df in df.groupby(level=0):
        for index, row in new_df.iterrows():
            new_df=new_df.groupby('name').first().loc([new_df['value']!='False'])
        return new_df
    return df

但我有这个错误

AttributeError: '_LocIndexer' object has no attribute 'groupby'

你能解释一下我的方法有什么问题吗?

【问题讨论】:

  • 你介意我尝试修改标题以使其更易于搜索吗?
  • @PaulH,当然,如果您认为它会更易于搜索!

标签: python pandas dataframe multi-level pandas-loc


【解决方案1】:

您的一般方法 - 使用循环 - 在 pandas 中很少按您想要的方式工作。

如果您有groupby 对象,则应使用applyaggfiltertransform 方法。在您的情况下,apply 是合适的。

您的主要目标如下:

所以最终的目标是删除所有的第一行(每个组定义为 )list 在(的)value(列)中有False

所以让我们编写一个简单的函数来在一个独立的数据帧上执行此操作:

def filter_firstrow_falses(df):
    if not df['value'].iloc[0]:
        return df.iloc[1:]
    else:
        return df

好的。很简单。

现在,让我们 apply 对您的真实数据框的每一组:

import pandas
from io import StringIO

csv = StringIO("""\
list,date_time,name,note,value
1,2015-05-22 05:37:59,Tom,129,False
1,2015-05-22 05:38:59,Tom,0,True
1,2015-05-22 05:39:59,Tom,0,False
1,2015-05-22 05:40:59,Tom,45,True
2,2015-05-22 05:37:59,Kate,129,True
2,2015-05-22 05:41:59,Kate,0,False
2,2015-05-22 05:37:59,Kate,0,True
""")

df = pandas.read_csv(csv)

final = (
    df.groupby(by=['list']) # create the groupby object
      .apply(filter_firstrow_falses) # apply our function to each group
      .reset_index(drop=True) # clean up the index
)
print(final)


   list            date_time  name  note  value
0     1  2015-05-22 05:38:59   Tom     0   True
1     1  2015-05-22 05:39:59   Tom     0  False
2     1  2015-05-22 05:40:59   Tom    45   True
3     2  2015-05-22 05:37:59  Kate   129   True
4     2  2015-05-22 05:41:59  Kate     0  False
5     2  2015-05-22 05:37:59  Kate     0   True

【讨论】:

  • 我只是在我的数据框@PaulH 上测试它,可能是因为我的False 不是布尔值而是字符串,它不会删除value 列中具有False 的第一行
  • 没关系,我只需将这行代码if not df['value'].iloc[0]: 更改为if df['value'].iloc[0]=='False' 就可以了!非常感谢您对回答方法的出色解释!
猜你喜欢
  • 2015-10-10
  • 1970-01-01
  • 1970-01-01
  • 2021-07-04
  • 2019-01-08
  • 2022-11-24
  • 2019-06-12
  • 2021-08-02
相关资源
最近更新 更多