Panda 删除行,除非另一个数据帧中两列中的字符串



我有一个这样的大数据框:

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项来查找给定字符串sli列表中的索引。我们使用next短路。

然后,对帧值的列表推导会查看每对leftrightleftstrrightstr列的字符串:它们所在的索引li相同吗?然后将相应的ref_val保留到列表中。

如果在li中根本找不到字符串,get_idx返回np.nan作为默认参数提供给next。由于np.nan比较不等于自身,因此我们不包括既没有找到leftsr也没有发现rightstrref_vals。最后,我们使用to_keepref 值查询帧以仅保留这些值,

要得到

>>> 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.extractmap在原始 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,最后使用列表理解和ziprightstr

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_strright_str然后在列表推导式中迭代 zip 对象,生成包含leftright字符串的元组,然后针对每个字符串sli测试是否存在s中的leftright,以创建布尔掩码

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

最新更新