[英]pandas delete row unless strings from two columns in another dataframe
我有一個像這樣的大數據框:
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
因此,例如,引用 49 被刪除,因為盡管 leftstr 和 rightstr 都在一個列表項中,但它們不在同一個列表項中。
這是一種方法:
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
函數查找給定字符串索引s
在列表li
通過對每個項目檢查li
。 我們將next
用於短路。
然后列表的理解在框架上看起來的值在每對left
和right
的字符串leftstr
和rightstr
列:是他們居住在指數li
一樣嗎? 然后將對應的ref_val
到一個列表中。
如果在li
根本找不到字符串, get_idx
會將np.nan
作為默認參數提供給next
。 由於np.nan
比較不等於本身,我們沒有包括ref_vals
其既不leftsr
也不rightstr
被發現。 最后,我們使用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
(如果您不想僅將 NumPy 用於np.nan
,則可以將其替換為float("nan")
。)
你可以試試這個:
# 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
這是使用merge
和列表理解的一種方法。 首先將您的列表轉換為測試 df,然后使用str.extract
和map
在原始 df 中使用leftstr
查找 ref :
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
,最后在rightstr
上使用帶有zip
列表理解:
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
然后遍歷一個列表理解其產生包含元組內的拉鏈對象left
和right
串然后為每個串s
在li
測試的存在left
和right
在s
,以便創建一個布爾掩碼
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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.