【问题标题】:Filter pandas DataFrame by membership in set-of-tags通过标签集的成员资格过滤 pandas DataFrame
【发布时间】:2015-03-04 17:55:56
【问题描述】:

假设我有一个包含一个列表或一组标签的 DataFrame,我想根据某个标签是否属于这一行来过滤 DataFrame,用 pandas 实现这一点最惯用的方法是什么?

import pandas as pd

df = pd.DataFrame({
    'amount': [15, 20, 40],
    'tags': [["Food", "Eating Out"], ["Food", "Groceries"], ["Clothes"]],
    'description': ["Garfunkel's", "Tesco", "Hollister"]
})

我有这段代码可以运行,但是写起来比较笨重:

criterion = lambda row: 'Food' in row['tags']
df[df.apply(criterion, axis=1)]

结果应该是:

【问题讨论】:

  • 在单个单元格中具有多个值在pandas 中并不是特别惯用的——我有时自己会这样做,但这使得使用典型的pandas 惯用语变得非常困难。考虑到您当前的解决方案看起来相当不错,我不确定您会得到多好。
  • 这是 Kaggle 购物比赛之一吗?
  • 事实上你可以将你的字符串转换成Categoricals,不需要每次都进行字符串匹配(假设完整的标签集是已知的)。
  • 哦,这很有趣,smci。是的,我实际上可以生成完整的标签集。
  • 单独的分类/布尔列比包含集合或列表的列要好,这会真正搞乱向量化。自己尝试并证明它。

标签: python pandas filter


【解决方案1】:

为了提高效率,每次要进行逻辑索引时都搜索字符串标签列表会很糟糕。所以:

df['tags'] 扩展为多列。 任一:

  • 如果最多有T个标签,则添加T个布尔列df['tFood'] = [ 'Food' in tt for tt in df['tags'] ]

  • 如果每个项目最多可以有 N 个标签并且 N 很小,则添加字符串列 tag1,tag2...tagN。事实上,您可以将字符串转换为分类,无需每次都进行字符串匹配。

现在,您可以快速进行逻辑索引:

df.loc[df['tFood']==True,]
# amount  description                tags tFood
# 0      15  Garfunkel's  [Food, Eating Out]  True
# 1      20        Tesco   [Food, Groceries]  True

【讨论】:

    【解决方案2】:

    您可以将lambda 仅应用于相关列,而不是整行:

    df[df['tags'].map(lambda tags: 'Food' in tags)]
    

    【讨论】:

    • 我曾经写过这样的代码,每次你想要进行逻辑索引时,搜索每一行的列表非常慢。 Set/list-of-string 在内存上也差很多。避免。
    • 谢谢,这似乎是使其工作的侵入性最小的更改,尽管@smci 绝对正确,我应该以不同的方式对我的数据进行切片以更有效地查询它。
    【解决方案3】:

    试试这个。它不是一个完美的解决方案,但它有效。

    print df[df['tags'].astype(str).str.contains('Food')]
    

    您甚至可以在 contains() 中使用正则表达式来匹配多个模式。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-12-22
      • 2022-11-15
      • 1970-01-01
      • 2020-09-24
      • 2017-08-25
      • 1970-01-01
      • 1970-01-01
      • 2021-09-05
      相关资源
      最近更新 更多