如何替换pandas.DataFrame中很少出现的某些列中的值,即出现频率较低(忽略NaN)的值?
例如,在下面的数据框中,假设我要替换列A或B中在其各自列中出现少于三次的任何值。我想将这些替换为“其他”:
import pandas as pd import numpy as np df = pd.DataFrame({'A':['ant','ant','cherry', pd.np.nan, 'ant'], 'B':['cat','peach', 'cat', 'cat', 'peach'], 'C':['dog','dog',pd.np.nan, 'emu', 'emu']}) df A | B | C | ---------------------- ant | cat | dog | ant | peach | dog | cherry | cat | NaN | NaN | cat | emu | ant | peach | emu |
换句话说,在A列和B列中,我想替换那些出现两次或更少(但不要理会NaN)的值。
所以我想要的输出是:
A | B | C | ---------------------- ant | cat | dog | ant | other | dog | other | cat | NaN | NaN | cat | emu | ant | other | emu |
这与先前发布的问题有关:从pandas.dataframe删除低频值
但那里的解决方案导致出现“ AttributeError:'NoneType'对象没有属性'any'。”(我想是因为我有NaN值?)
这与根据value_counts()在pandas数据框中更改值非常相似。您可以向lambda函数添加条件以排除列“ C”,如下所示:
df.apply(lambda x: x.mask(x.map(x.value_counts())<3, 'other') if x.name!='C' else x) Out: A B C 0 ant cat dog 1 ant other dog 2 other cat NaN 3 NaN cat emu 4 ant other emu
这基本上是遍历列。对于每一列,它都会生成值计数并将该系列用于映射。这允许x.mask
检查条件计数是否小于3。如果是这样,它将返回“ other”,否则返回实际值。最后,条件检查列名。
拉姆达的情况可以通过将其更改为一概而论多个列x.name not in 'CDEF'
或x.name not in ['C', 'D', 'E', 'F']
从x.name!='C'
。