【问题标题】:Remove dataframe row containing a specific in a list value from a list从列表中删除包含列表中特定值的数据框行
【发布时间】:2021-08-18 20:44:23
【问题描述】:

我有一个数据框 df:

    A   B   C   D   E
0   string1 string4 [string7, string10, ...] [string11, string 12] [string15, ...]
1   string2 string5 [string8, ...] [string13, ...] [string16, ...]
2   string3 string6 [string9, ...] [string14, ...] [string17, ...]

还有一个列表to_delete

to_delete = [string7, string9, string17]

我想删除数据框中包含to_delete 中的字符串的所有行,但我不知道如何将.isin 与列表一起使用。

【问题讨论】:

    标签: python pandas list dataframe


    【解决方案1】:

    您可以按以下步骤处理:

    1. 您可以在每个列/元素上使用pd.Series.explode() 将字符串列表展开为多行,每行仅包含字符串(所有列表都已展开/分解为行)。

    2. 然后使用.isin()检查to_delete列表中字符串的数据框。

    3. 按索引级别 0(包含分解前的原始行索引)分组,将匹配结果的多行聚合汇总为一行(使用 groupby() 下的 .sum())。

    4. 然后.sum(axis=1) 逐行检查要删除的任何匹配字符串。

    5. 检查匹配为 0 的行(要保留的行)并形成结果行的布尔索引。

    6. 最后,使用.loc过滤没有匹配到保留的行。


    df.loc[df.apply(pd.Series.explode).isin(to_delete).groupby(level=0).sum().sum(axis=1).eq(0)]
    

    结果:

             A        B          C           D           E
    1  string2  string5  [string8]  [string13]  [string16]
    

    可以通过以下代码构建原始数据框进行测试:

    data = {'A': ['string1', 'string2', 'string3'],
     'B': ['string4', 'string5', 'string6'],
     'C': [['string7', 'string10'], ['string8'], ['string9']],
     'D': [['string11', 'string 12'], ['string13'], ['string14']],
     'E': [['string15'], ['string16'], ['string17']]}
    
     df = pd.DataFrame(data)
    

    【讨论】:

    • 感谢您的所有解释!
    【解决方案2】:

    我看到已经有几个答案,但如果可以的话,我想加入我的答案。我认为SeaBean's solution 也是正确的,我喜欢它,与other proposed solution 不同,您不必指定哪些列具有列表。

    我无法像 SeaBean 一样解释我的解决方案,因为这是我不久前遇到的问题,老实说,我通过反复试验想出了它。

    d = {'A':['string1','string2','string3'],
         'B':['string4','string5','string6'],
         'C':[['string7','string10'],['string8'],['string9']],
         'D':[['string11','string12'],['string13'],['string14']]
         'E':[['string15'],['string16'],['string17']]}
    df = pd.DataFrame(data=d);
    res = df[~df.stack().explode().isin(to_delete).any(level=0)]
    

    我已经尝试用更多的项目来计时,看来我的解决方案要好一些。

    d = {'A':['string1','string2','string3']*10000, 'B':['string4','string5','string6']*10000, 'C':[['string7','string10'],['string8'],['string9']]*10000,'D':[['string11','string12'],['string13'],['string14']]*10000,'E':[['string15'],['string16'],['string17']]*10000}
    df = pd.DataFrame(data=d);
    
    to_delete = ['string7', 'string9', 'string17']
    
    
    start = time.time()
    print(df[~df.stack().explode().isin(to_delete).any(level=0)])
    end = time.time()
    print(end - start)
    
    start = time.time()
    print(df.loc[df.apply(pd.Series.explode).isin(to_delete).groupby(level=0).sum().sum(axis=1).eq(0)])
    end = time.time()
    print(end - start)
    

    输出:

                 A        B          C           D           E
    1      string2  string5  [string8]  [string13]  [string16]
    4      string2  string5  [string8]  [string13]  [string16]
    7      string2  string5  [string8]  [string13]  [string16]
    10     string2  string5  [string8]  [string13]  [string16]
    13     string2  string5  [string8]  [string13]  [string16]
    ...        ...      ...        ...         ...         ...
    29986  string2  string5  [string8]  [string13]  [string16]
    29989  string2  string5  [string8]  [string13]  [string16]
    29992  string2  string5  [string8]  [string13]  [string16]
    29995  string2  string5  [string8]  [string13]  [string16]
    29998  string2  string5  [string8]  [string13]  [string16]
                                                              
    [10000 rows x 5 columns]                                  
    0.08804535865783691                                       
                 A        B          C           D           E
    1      string2  string5  [string8]  [string13]  [string16]
    4      string2  string5  [string8]  [string13]  [string16]
    7      string2  string5  [string8]  [string13]  [string16]
    10     string2  string5  [string8]  [string13]  [string16]
    13     string2  string5  [string8]  [string13]  [string16]
    ...        ...      ...        ...         ...         ...
    29986  string2  string5  [string8]  [string13]  [string16]
    29989  string2  string5  [string8]  [string13]  [string16]
    29992  string2  string5  [string8]  [string13]  [string16]
    29995  string2  string5  [string8]  [string13]  [string16]
    29998  string2  string5  [string8]  [string13]  [string16]
                                                              
    [10000 rows x 5 columns]                                  
    0.11187744140625                                          
    
    

    【讨论】:

      【解决方案3】:

      我能想到的最糟糕的解决方案是使用apply

      g = lambda x: (set(to_delete) - df[x].apply(set)).str.len()==len(to_delete)
      
      res = df[g('C') & g('D') & g('E')]
      

      df(输入):

          A           B           C                       D                       E
      0   string1     string4     [string7, string10]     [string11, string12]    [string15]
      1   string2     string5     [string8]               [string13]              [string16]
      2   string3     string6     [string9]               [string14]              [string17]
      

      分辨率:

          A           B           C            D          E
      1   string2     string5     [string8]   [string13]  [string16]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-11-04
        • 2019-05-25
        • 1970-01-01
        • 2014-03-18
        • 1970-01-01
        • 2022-12-31
        • 2017-09-27
        相关资源
        最近更新 更多