如何有效地找到包含列表项的数据框行?
How to efficiently find dataframe row that contains items from list?
假设我有以下示例
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_*,因此标题中的 "efficiently"。 "df" 的列数将在 10 到 20 之间。此外,将有数千个 "items" 列表包含 10 到 20 个元素。
有人可以帮我解决这个问题吗?
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 等)。它将查看此列表中的每个项目,并检查它是否在您要检查的项目列表中。
如果它发现一个项目不在您正在检查的项目列表中,它将 return 它发现一个项目不在您的检查列表中。这似乎是您正在寻找的,任何不在第一个标记为 "items" 的项目列表中的值。所以这会检查那些,从这里你可以很容易地丢弃那些。
通常在搜索大数据集时,二进制搜索是可行的方法,但是在这种情况下这似乎不太可行,除非你可以将 df 列表按字母顺序排列,如果你不能我会做我的上面写了
希望这是有道理的!
我们需要找到一种方法来确认行完全在 items
列表中,同时仍然考虑空条目。 isin, sum and 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
另一个解决方案:
如果您的数据框如下所示:
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
使用 ~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
假设我有以下示例
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_*,因此标题中的 "efficiently"。 "df" 的列数将在 10 到 20 之间。此外,将有数千个 "items" 列表包含 10 到 20 个元素。
有人可以帮我解决这个问题吗?
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 等)。它将查看此列表中的每个项目,并检查它是否在您要检查的项目列表中。
如果它发现一个项目不在您正在检查的项目列表中,它将 return 它发现一个项目不在您的检查列表中。这似乎是您正在寻找的,任何不在第一个标记为 "items" 的项目列表中的值。所以这会检查那些,从这里你可以很容易地丢弃那些。
通常在搜索大数据集时,二进制搜索是可行的方法,但是在这种情况下这似乎不太可行,除非你可以将 df 列表按字母顺序排列,如果你不能我会做我的上面写了
希望这是有道理的!
我们需要找到一种方法来确认行完全在 items
列表中,同时仍然考虑空条目。 isin, sum and 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
另一个解决方案:
如果您的数据框如下所示:
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
使用 ~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