【问题标题】:Pandas: Replace a string with 'other' if it is not present in a list of stringsPandas:如果字符串列表中不存在字符串,则将其替换为“其他”
【发布时间】:2018-12-21 17:05:02
【问题描述】:

我有以下数据框 df,列为“类”

    Class
0   Individual
1   Group
2   A
3   B
4   C
5   D
6   Group

我想将除 Group 和 Individual 之外的所有内容都替换为“Other”,因此最终的数据框是

    Class
0   Individual
1   Group
2   Other
3   Other
4   Other
5   Other
6   Group

数据框很大,有超过 60 万行。以最佳方式查找“组”和“个人”以外的值并将其替换为“其他”的最佳方法是什么?

我见过replace的例子,比如:

df['Class'] = df['Class'].replace({'A':'Other', 'B':'Other'})

但由于我拥有的唯一值数量太多,我无法单独执行此操作。我只想使用“组”和“个人”的排除子集。

【问题讨论】:

  • 如果只有GroupIndividual存在,你可以使用replace all if not in ['Group', 'Individual']这样的条件

标签: python python-3.x pandas


【解决方案1】:

我认为你需要:

df['Class'] = np.where(df['Class'].isin(['Individual','Group']), df['Class'], 'Other')
print (df)
        Class
0  Individual
1       Group
2       Other
3       Other
4       Other
5       Other
6       Group

另一种解决方案(较慢):

m = (df['Class'] == 'Individual') | (df['Class'] == 'Group')
df['Class'] = np.where(m, df['Class'], 'Other')

另一种解决方案:

df['Class'] = df['Class'].map({'Individual':'Individual', 'Group':'Group'}).fillna('Other')

性能(实际数据取决于替换次数):

#[700000 rows x 1 columns]
df = pd.concat([df] * 100000, ignore_index=True)
#print (df)

In [208]: %timeit df['Class1'] = np.where(df['Class'].isin(['Individual','Group']), df['Class'], 'Other')
25.9 ms ± 485 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [209]: %timeit df['Class2'] = np.where((df['Class'] == 'Individual') | (df['Class'] == 'Group'), df['Class'], 'Other')
120 ms ± 6.63 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [210]: %timeit df['Class3'] = df['Class'].map({'Individual':'Individual', 'Group':'Group'}).fillna('Other')
95.7 ms ± 3.85 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [211]: %timeit df.loc[~df['Class'].isin(['Individual', 'Group']), 'Class'] = 'Other'
97.8 ms ± 6.78 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

【讨论】:

  • 哇!这太棒了:) 我现在已经采用了第三种解决方案。但是以后会使用第一个解决方案。
【解决方案2】:

例如,您可以这样做

  1. 获取唯一项目列表list = df['Class'].unique()
  2. 删除你的已知类list.remove('Individual')....
  3. 然后列出所有其他行df[df.class is in list]
  4. 替换类值df[df.class is in list].class = 'Other'

对不起这个伪伪代码,但原理是一样的。

【讨论】:

    【解决方案3】:

    另一种方法可能是:

    df.loc[~df['Class'].isin(['Individual', 'Group']), 'Class'] = 'Other'
    

    【讨论】:

      【解决方案4】:

      你可以使用pd.Series.where:

      df['Class'].where(df['Class'].isin(['Individual', 'Group']), 'Other', inplace=True)
      
      print(df)
      
              Class
      0  Individual
      1       Group
      2       Other
      3       Other
      4       Other
      5       Other
      6       Group
      

      这应该比map + fillna 更有效:

      df = pd.concat([df] * 100000, ignore_index=True)
      
      %timeit df['Class'].where(df['Class'].isin(['Individual', 'Group']), 'Other')
      # 60.3 ms per loop
      
      %timeit df['Class'].map({'Individual':'Individual', 'Group':'Group'}).fillna('Other')
      # 133 ms per loop
      

      【讨论】:

        【解决方案5】:

        使用apply 的另一种方式:

        df['Class'] = df['Class'].apply(lambda cl : cl if cl in ["Individual","Group"] else "Other"]
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-01-02
          • 2023-01-30
          • 2012-07-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多