如果计数小于熊猫阈值,则填充默认值

时间:2018-07-11 08:57:29

标签: python pandas dataframe

我有一个数据框:

import pandas as pd
import numpy as np

df = pd.DataFrame()
df['name'] = ['john','sam','john','john','dean','dean','maggi',
              'ram','maggi','ana','sam','sam']
df['pt'] = [23, 32, 45, 65, 65, 45, 32, 45, 90, 10, 32, 22]

如果名称在名称列中仅出现一次,我想用其他名称替换。

所以我的输出将是:

     name  pt
0    john  23
1     sam  32
2    john  45
3    john  65
4    dean  65
5    dean  45
6   maggi  32
7   other  45
8   maggi  90
9   other  10
10    sam  32
11    sam  22

在我的原始数据中,值有数百个,因此使用 df.replacemap是不可行的。

np.where仅适用于二进制列。所以我被困在这里。

谢谢

2 个答案:

答案 0 :(得分:4)

numpy.whereduplicated一起使用以选择所有唯一的行,或者将transformsize一起使用以指定阈值来进行更通用的解决方案:

df['name'] = np.where(~df['name'].duplicated(keep=False), 'other', df['name'])

或者:

df['name'] = np.where(df.groupby('name')['name'].transform('size') == 1, 'other', df['name'])
print (df)
     name  pt
0    john  23
1     sam  32
2    john  45
3    john  65
4    dean  65
5    dean  45
6   maggi  32
7   other  45
8   maggi  90
9   other  10
10    sam  32
11    sam  22

另一种解决方案,谢谢@乔恩·克莱门茨(Jon Clements):

df.name.where(df.groupby('name')['name'].transform('size') > 1, 'other', inplace=True)

答案 1 :(得分:3)

这是使用pd.Series.value_countspd.DataFrame.loc的矢量化解决方案:

s = df['name'].value_counts(sort=False)
df.loc[df['name'].isin(s[s == 1].index), 'name'] = 'other'

print(df)

     name  pt
0    john  23
1     sam  32
2    john  45
3    john  65
4    dean  65
5    dean  45
6   maggi  32
7   other  45
8   maggi  90
9   other  10
10    sam  32
11    sam  22

性能基准化

如果您有很多重复的名字,可以使用Categorical Data来提高性能。以下是Python 3.6,Pandas 0.19上的计时。

def jpp(df):
    s = df['name'].value_counts(sort=False)
    df.loc[df['name'].isin(s[s == 1].index), 'name'] = 'other'
    return df

def jez(df):
    df['name'] = np.where(df.groupby('name')['name'].transform('size') == 1, 'other', df['name'])
    return df

def jon(df):
    df['name'] = df['name'].apply(lambda name, counts=Counter(df['name']): name if counts[name] > 1 else 'other')
    return df

assert jpp(df).equals(jez(df))
assert jpp(df).equals(jon(df))

%timeit jpp(df)  # 49.4 ms per loop
%timeit jez(df)  # 56.2 ms per loop
%timeit jon(df)  # 274 ms per loop

设置

df = pd.DataFrame({'name': ['john','sam','john','john','dean','dean','maggi',
                            'ram','maggi','ana','sam','sam'],
                   'pt': [23, 32, 45, 65, 65, 45, 32, 45, 90, 10, 32, 22]})

df['name'] = df['name'].astype('category')
df['name'] = df['name'].cat.add_categories('other')

df = pd.concat([df, pd.concat([df.iloc[:5]]*100000)])