【问题标题】:Failed to filter rows containing a specific value in the index column after resetting index重置索引后无法过滤索引列中包含特定值的行
【发布时间】:2019-02-18 15:02:05
【问题描述】:

我正在组织一些计划的数据,其中包含计划阶段的信息,P(初步)或F(最终)。我正在使用 pandas 文档中examples 中显示的方法。

df1 = pd.read_excel('FilePath', sheetname = 'ForFilter')
df1


landuse_SUB_ID  TYPE    RECD_DATE   PHASE   LAND_USE    CPACTIONDA
0   24  1   2000-04-07  P   ROW 2000-05-04
1   24  1   2000-04-07  P   NONE    2000-05-04
2   25  1   2000-08-10  P   COMM    2000-09-08
3   34  1   2000-04-14  F   REC 2000-04-14
4   34  1   2000-04-14  F   SFD 2000-04-14
5   35  1   2000-01-20  P   NONE    2000-02-02
6   42  1   2000-04-04  P   SFD 2000-05-01
7   42  1   2000-12-06  P   SFD 2001-01-03
8   43  1   2000-09-07  P   NONE    2000-09-21
9   51  1   2000-11-10  P   NONE    2000-11-28
10  53  1   2000-02-22  F   SFD 2000-02-22

在使用了示例中的方法(使用likeregex)之后,在我看来这些方法只能过滤索引列中的值。因此我更改了索引:

df1_filter1 = df1.set_index('PHASE')


landuse_SUB_ID  TYPE    RECD_DATE   LAND_USE    CPACTIONDA
PHASE                   
P   24  1   2000-04-07  ROW 2000-05-04
P   24  1   2000-04-07  NONE    2000-05-04
P   25  1   2000-08-10  COMM    2000-09-08
F   34  1   2000-04-14  REC 2000-04-14
F   34  1   2000-04-14  SFD 2000-04-14
P   35  1   2000-01-20  NONE    2000-02-02
P   42  1   2000-04-04  SFD 2000-05-01
P   42  1   2000-12-06  SFD 2001-01-03
P   43  1   2000-09-07  NONE    2000-09-21
P   51  1   2000-11-10  NONE    2000-11-28
F   53  1   2000-02-22  SFD 2000-02-22

现在数据框使用Phase作为索引,我使用like方法过滤df1_filter1

df1_filter1.filter(like = 'F', axis = 0)

我得到了错误

“ValueError:无法从重复的轴重新索引”

这对我来说似乎是一个非常简单的操作,所以我只是想知道我做错了什么导致了这个错误。对于我的问题,什么是最好的方法(最少的步骤和最干净的代码)。

【问题讨论】:

  • 我无法重现此问题。当我运行您的代码时,我得到一个过滤的数据框,其中包含由 F 索引的 3 行
  • @Andrew 那太荒谬了。我会再试一次。请问一下过滤器文档中使用的方法? like = ABC 是否过滤值仅为ABC 或包含ABC 的行? regex = 'e$' 是否意味着过滤以e 结尾的行?谢谢。

标签: python pandas filter


【解决方案1】:

filter 可能直观地感觉是正确的函数,但您几乎可以肯定应该使用loc 来过滤您的数据(在上面的示例链接中,它在一个黄色的大框中显示“另见:loc”)。对于这个简单的示例,您还可以使用布尔索引:

>>> df1.loc[df1['PHASE'] == 'F']  # or boolean indexing via df1[df1['PHASE'] == 'F']
    landuse_SUB_ID  TYPE   RECD_DATE PHASE LAND_USE  CPACTIONDA
3               34     1  2000-04-14     F      REC  2000-04-14
4               34     1  2000-04-14     F      SFD  2000-04-14
10              53     1  2000-02-22     F      SFD  2000-02-22

【讨论】:

  • 非常感谢,我确实在其他帖子中看到了这个解决方案。但我最初搜索“过滤器”方法只是想让它工作。而对于这种方法,我可以使用 iloc 来实现同样的事情吗?还有一个单独的问题,我也不确定如何在过滤器中使用 like 和 regex。 like = ABC 是否过滤值仅为ABC 或包含ABC 的行? regex = 'e$' 是否意味着过滤以e 结尾的行?再次感谢。
  • iloc 用于按列号索引,从零开始。因此,您可以通过 df1[df1.iloc[:, 3] == 'F'] 将布尔索引与 iloc 一起使用。
  • 技术上你也可以做到df1.iloc[(df1['PHASE'] == 'F').values]iloc 有一些微妙但很少使用的功能。
  • 哦,我认为 loc 和 iloc 之间的唯一区别是 iloc 可以使用数字而不是像 loc 那样拼写列名。您展示的这两种过滤方法略有不同。我对此还是很陌生。我可以将df1[df1.iloc[:, 3] == 'F'] 理解为dataframe[slice criteria]'? Then why can df1.loc` 后跟[slice criteria] 吗?谢谢。很抱歉用问题轰炸了你,
  • @BowenLiu,从系列中提取 NumPy 数组,请参阅 pd.Series.values
【解决方案2】:

正如已经指出的,对于这个任务,filter 不是必需的。在@Alexander's answer 中使用loc。作为替代方案,您也可以使用query:

df1.query('PHASE == "F"')

    landuse_SUB_ID  TYPE   RECD_DATE PHASE LAND_USE  CPACTIONDA
3               34     1  2000-04-14     F      REC  2000-04-14
4               34     1  2000-04-14     F      SFD  2000-04-14
10              53     1  2000-02-22     F      SFD  2000-02-22

filter 也适合我:

df1_filter1 = df1.set_index('PHASE')
df1_filter1.filter(like='F', axis=0)

       landuse_SUB_ID  TYPE   RECD_DATE LAND_USE  CPACTIONDA
PHASE                                                       
F                  34     1  2000-04-14      REC  2000-04-14
F                  34     1  2000-04-14      SFD  2000-04-14
F                  53     1  2000-02-22      SFD  2000-02-22

关于您对regex的使用的问题:

df2 = df1.set_index('LAND_USE')
df2.filter(regex="E$", axis=0)

          landuse_SUB_ID  TYPE   RECD_DATE PHASE  CPACTIONDA
LAND_USE                                                    
NONE                  24     1  2000-04-07     P  2000-05-04
NONE                  35     1  2000-01-20     P  2000-02-02
NONE                  43     1  2000-09-07     P  2000-09-21
NONE                  51     1  2000-11-10     P  2000-11-28

在这里过滤所有以E 结尾的行。

您可以通过例如正在做:

df1[df1['LAND_USE'].str.endswith('E')]

   landuse_SUB_ID  TYPE   RECD_DATE PHASE LAND_USE  CPACTIONDA
1              24     1  2000-04-07     P     NONE  2000-05-04
5              35     1  2000-01-20     P     NONE  2000-02-02
8              43     1  2000-09-07     P     NONE  2000-09-21
9              51     1  2000-11-10     P     NONE  2000-11-28

filter 的问题在于,您随后会创建一个具有非唯一值的索引,这通常是个坏主意。所以,我会选择.loc.query

【讨论】:

  • 非常感谢先生。我想不出比这更好的答案了。在我看来,查询是我在问题中提出的特定目的的最佳方式,因为它具有最短/最干净的代码。不知何故,在我的家用笔记本电脑上filter 正在工作。如果我可以再问一个我刚刚想到的问题,因为我仍在学习 pandas 可以做什么:如何根据列名包含的特定字符串过滤/查询列?例如,我想查看所有名称为“...日期”的列。再次感谢
  • @BowenLiu:很高兴我能帮上忙。您也可以将filter 用于列名;对于您的示例 df.filter(regex="date$") 应该可以工作(获取所有以 date 结尾的列)。
  • 谢谢。我一直在努力寻找更多关于如何在熊猫过滤器中使用regexlike 的信息,但还没有运气。你有什么链接可以分享吗?我的印象是like 表示包含而不是==。我是对的吗?再次感谢。
  • @BowenLiu:我认为文档中的示例很有启发性。我建议创建一个玩具示例,然后通过玩来探索不同的选项。如果您随后观察到意外行为,您可以提出一个新问题 :)
猜你喜欢
  • 1970-01-01
  • 2023-03-29
  • 1970-01-01
  • 1970-01-01
  • 2016-08-16
  • 2022-11-15
  • 1970-01-01
  • 1970-01-01
  • 2022-11-21
相关资源
最近更新 更多