代码之家  ›  专栏  ›  技术社区  ›  redwolf_cr7

pandas:如果字符串列表中没有“other”,则将其替换为

  •  2
  • redwolf_cr7  · 技术社区  · 7 年前

    我有以下数据框,df,列'class'

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

    我想用'other'替换除group和individual之外的所有内容,因此最终的数据框架是

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

    数据帧很大,有超过600k行。除了“群体”和“个人”之外,最好的方法是什么?用“其他”来代替它们?

    我见过替换的例子,例如:

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

    但由于我拥有的独特价值观太多,我无法单独做到这一点。我只想使用“group”和“individual”的排除子集。

    4 回复  |  直到 7 年前
        1
  •  6
  •   jezrael    7 年前

    我认为需要:

    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
    

    另一个解决方案(Slowier):

    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
  •  2
  •   zipa    7 年前

    另一种方法是:

    df.loc[~df['Class'].isin(['Individual', 'Group']), 'Class'] = 'Other'
    
        3
  •  1
  •   Ashwel    7 年前

    你可以这样做例如

    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'

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

        4
  •  1
  •   jpp    7 年前

    你可以用 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