簡體   English   中英

熊貓刪除行,除非來自另一個數據幀中兩列的字符串

[英]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用於短路。

然后列表的理解在框架上看起來的值在每對leftright的字符串leftstrrightstr列:是他們居住在指數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.extractmap在原始 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_strright_str然后遍歷一個列表理解其產生包含元組內的拉鏈對象leftright串然后為每個串sli測試的存在leftrights ,以便創建一個布爾掩碼

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM