如何有效地查找包含列表中项目的数据框行?
Posted
技术标签:
【中文标题】如何有效地查找包含列表中项目的数据框行?【英文标题】:How to efficiently find dataframe row that contains items from list? 【发布时间】:2020-10-06 15:53:19 【问题描述】:假设我有以下示例
items = ['milk', 'bread', 'water']
df:
name item1 item2 item3
items_1 milk water
items_2 milk rubber juice
items_3 juice paper wood
items_4 bread
items_5 bread water milk
items_6 milk juice
在此示例中,我想获取其成员完全在项目列表中的所有 df 行,这意味着:
items_1 items_4 items_5现在,真正的“df”数据框将包含数百万行,即 items_*,因此标题中的“高效”。 “df”的列数将在 10 到 20 之间。此外,将有数千个包含 10 到 20 个元素的“items”列表。
有人可以帮我解决这个问题吗?
【问题讨论】:
当你说完全在列表中时,你的意思是牛奶、面包、水都必须在行中正确吗? 取 items_1 行,检查该行中的每个项目是否也在项目列表中。在这种情况下,牛奶和水都在项目列表中(牛奶、面包、水),这是我感兴趣的行。此外, items_4 行下的所有内容(在本例中只是面包)都包含在项目列表中。希望这能稍微澄清一下问题。 【参考方案1】: for item in dflist:
if item not in items:
print("this df list has an items that is not in the items list")
我知道输出可能不是您想要的输出,但您的理想输出尚不清楚。
这个 for 循环的作用是循环遍历 df 列表中的每个项目(例如 items_1、items_2 等)。它将查看此列表中的每个项目,并检查它是否在您要检查的项目列表中。
如果它找到一个不在您正在检查的项目列表中的项目,它将返回它找到一个不在您的检查列表中的项目。这似乎是您正在寻找的,任何不在标有“项目”的项目的第一个列表中的值。因此,这会检查这些内容,您可以从这里轻松丢弃这些内容。
通常在搜索大数据集时,二进制搜索是要走的路,但是在这种情况下这似乎不可行,除非你可以按字母顺序排列 df 列表,如果你不能,我会按照我上面写的.
希望这是有道理的!
【讨论】:
【参考方案2】:我们需要找到一种方法来确认行完全在items
列表中,同时仍然考虑空条目。 isin、sum 和 notna 的组合可以提供帮助:
#set name as index
#allows us to focus on the items columns
#and later allows easy filtering
df = df.set_index("name")
#find rows that are in items
#and get the sum of the boolean
A = df.isin(items).sum(1)
#get the sum of rows
#that are not boolean
#this helps us narrow down
#items completely in the items list
#that are yet affected by null entries
B = df.notna().sum(1)
#compare A and B
#if they match, that implies complete entry in items list
cond = A.eq(B)
#let's see what cond looks :
cond
name
items_1 True
items_2 False
items_3 False
items_4 True
items_5 True
items_6 False
dtype: bool
#filter df with condition to get your rows
df.loc[cond]
item1 item2 item3
name
items_1 milk water None
items_4 bread None None
items_5 bread water milk
【讨论】:
【参考方案3】:另一种解决方案:
如果您的数据框如下所示:
import pandas as pd
from io import StringIO
txt = '''name item1 item2 item3
items_1 milk water
items_2 milk rubber juice
items_3 juice paper wood
items_4 bread
items_5 bread water milk
items_6 milk juice'''
items = ['milk', 'bread', 'water']
df = pd.read_fwf(StringIO(txt))
df = df.fillna('').set_index('name')
print(df)
item1 item2 item3
name
items_1 milk water
items_2 milk rubber juice
items_3 juice paper wood
items_4 bread
items_5 bread water milk
items_6 milk juice
你可以这样做:
items = pd.Series(items + [''])
m = df.apply(lambda x: x.isin(items).all(), axis=1)
print(df[m])
打印:
item1 item2 item3
name
items_1 milk water
items_4 bread
items_5 bread water milk
【讨论】:
【参考方案4】:使用 ~isin 检查条件是否对所有值都不为真,获取索引,使用布尔索引。你得到
true_names = df[~df.iloc[:, 1:].isin(items)].isnull().all(1)
df.loc[true_names, 'name']
0 name_1
3 name_4
4 name_5
【讨论】:
感谢您的回答。我试过你的建议,它确实加快了执行时间。也会尝试其他答案,看看是否有一些解决方案比你的更快。以上是关于如何有效地查找包含列表中项目的数据框行?的主要内容,如果未能解决你的问题,请参考以下文章