我有一个这样的大数据框:
ref leftstr rightstr
12 fish 10 47 red A45
49 abc bread x10 green 12
116 19 cheese 19A blue blue 4040
118 8 fish 9fish A10 red B11
200 cheese 000 99 green 98
240 142Z cheese B blue 42 12
450 bread 94.16 0.6 red blue
...
还有这样的大列表:
li = [
'47 red A45 bread fish 10',
'cheese 000 [purple] orangeA 99 green 98',
'bread 94.16 green 12',
'0.6 red blue abc bread x10',
'bread 19 cheese 19A 100 blue blue 4040',
'8 fish 9fish 0.6 red blue',
'bread fish 10 red A45'
...
]
如果 leftstr 和 rightstr 中的确切字符串不都存在于列表的任何项目(但它必须是同一项目)中,我想从 df 中删除行。无论 leftstr 还是 rightstr 首先出现在列表项中,或者列表项中是否有文本以及 leftstr 和 rightstr,都无关紧要。
Desired output:
ref leftstr rightstr
12 fish 10 47 red A45
116 19 cheese 19A blue blue 4040
200 cheese 000 99 green 98
因此,例如,ref 49 被删除,因为尽管 leftstr 和 rightstr 都在一个列表项中,但它们不在同一个列表项中。
你可以试试这个:
# Identify rows to keep
rows_to_keep = []
for item in li:
for i, row, in df.iterrows():
if row["leftstr"] in item and row["rightstr"] in item:
rows_to_keep.append(row["ref"])
# Select rows
filtered_df = df[df["ref"].isin(rows_to_keep)]
print(filtered_df)
# Outputs
ref leftstr rightstr
0 12 fish 10 47 red A45
2 116 19 cheese 19A blue blue 4040
4 200 cheese 000 99 green 98
这是一种方法:
get_idx = lambda s: next((idx for idx, item in enumerate(li) if s in item), np.nan)
to_keep = [ref_val
for ref_val, left, right in df.to_numpy()
if get_idx(left) == get_idx(right)]
ndf = df.query("ref == @to_keep")
其中,get_idx
函数通过检查每个li
项来查找给定字符串s
li
列表中的索引。我们使用next
短路。
然后,对帧值的列表推导会查看每对left
和right
leftstr
和rightstr
列的字符串:它们所在的索引li
相同吗?然后将相应的ref_val
保留到列表中。
如果在li
中根本找不到字符串,get_idx
返回np.nan
作为默认参数提供给next
。由于np.nan
比较不等于自身,因此我们不包括既没有找到leftsr
也没有发现rightstr
的ref_vals
。最后,我们使用to_keep
ref 值查询帧以仅保留这些值,
要得到
>>> ndf
ref leftstr rightstr
0 12 fish 10 47 red A45
2 116 19 cheese 19A blue blue 4040
4 200 cheese 000 99 green 98
(如果不想只对np.nan
使用 NumPy,可以将其替换为float("nan")
。
这是使用merge
和列表理解的一种方法。首先将列表投射到测试 df 中,然后使用str.extract
和map
在原始 df 中查找 ref 并带有leftstr
:
test = pd.DataFrame({"name":li})
test["ref"] = (test["name"].str.extract(f'({"|".join(df["leftstr"])})', expand=False)
.map(df.set_index("leftstr")["ref"]))
print (test)
name ref
0 47 red A45 bread fish 10 12
1 cheese 000 [purple] orangeA 99 green 98 200
2 bread 94.16 green 12 450
3 0.6 red blue abc bread x10 49
4 bread 19 cheese 19A 100 blue blue 4040 116
5 8 fish 9fish 0.6 red blue 118
6 bread fish 10 red A45 12
现在做一个merge
,最后使用列表理解和zip
rightstr
:
new = df.merge(test, on='ref')
print (new[[x in y for x, y in zip(new["rightstr"], new["name"])]])
ref leftstr rightstr name
0 12 fish 10 47 red A45 47 red A45 bread fish 10
3 116 19 cheese 19A blue blue 4040 bread 19 cheese 19A 100 blue blue 4040
5 200 cheese 000 99 green 98 cheese 000 [purple] orangeA 99 green 98
zip
列left_str
和right_str
然后在列表推导式中迭代 zip 对象,生成包含left
和right
字符串的元组,然后针对每个字符串s
li
测试是否存在s
中的left
和right
,以创建布尔掩码
mask = [next((True for s in li if l in s and r in s), False)
for l, r in zip(df['leftstr'], df['rightstr'])]
<小时 />>>> df[mask]
ref leftstr rightstr
0 12 fish 10 47 red A45
2 116 19 cheese 19A blue blue 4040
4 200 cheese 000 99 green 98