替换pandas数据帧中很少出现的值

时间:2014-03-05 20:31:37

标签: python pandas

我有一个中等大小(约60,000行乘15列)的csv文件,我正在使用pandas。每行代表一个人并包含个人数据。我想匿名呈现数据。我想要这样做的一种方法是替换特殊列中罕见的值。我最初尝试这样做:

def clean_data(entry):
    if df[df.column_name == entry].index.size < 10:
        return 'RARE_VALUE'
    else:
        return entry

df.new_column_name = df.column_name.apply(clean_data)

但每次运行它都冻结了我的系统。不幸的是,这意味着我没有有用的调试数据。有谁知道这样做的正确方法?该列包含字符串和空值。

2 个答案:

答案 0 :(得分:8)

我认为你想分组列名:

g = df.groupby('column_name')

例如,您可以使用过滤器仅返回column_name中出现次数超过10次的行:

g.filter(lambda x: len(x) >= 10)

要使用'RARE_VALUE'覆盖列,您可以使用transform(为每个组计算结果一次,并适当地展开它):

df.loc[g[col].transform(lambda x: len(x) < 10).astype(bool), col] = 'RARE_VALUE'

正如DSM指出的那样,以下技巧更快更多

df.loc[df[col].value_counts()[df[col]].values < 10, col] = "RARE_VALUE"

以下是一些时间信息(以显示DSM的解决方案令人印象深刻!):

In [21]: g = pd.DataFrame(np.random.randint(1, 100, (1000, 2))).groupby(0)

In [22]: %timeit g.filter(lambda x: len(x) >= 10)
10 loops, best of 3: 67.2 ms per loop

In [23]: %timeit df.loc[g[1].transform(lambda x: len(x) < 10).values.astype(bool), 1]
10 loops, best of 3: 44.6 ms per loop

In [24]: %timeit df.loc[df[1].value_counts()[df[1]].values < 10, 1]
1000 loops, best of 3: 1.57 ms per loop

答案 1 :(得分:0)

@Andy Hayden 以各种方式解决了这个问题。不过,我建议将 pipelines 用于此类任务。以下可能看起来更笨拙,但如果您想将整个管道保存为一个对象,或者您必须在测试集上概括预测,它就会派上用场:

class RemoveScarceValuesFeatureEngineer:

    def __init__(self, min_occurences):
        self._min_occurences = min_occurences
        self._column_value_counts = {}

    def fit(self, X, y):
        for column in X.columns:
            self._column_value_counts[column] = X[column].value_counts()
        return self

    def transform(self, X):
        for column in X.columns:
            X.loc[self._column_value_counts[column][X[column]].values
                  < self._min_occurences, column] = "RARE_VALUE"

        return X

    def fit_transform(self, X, y):
        self.fit(X, y)
        return self.transform(X)

您可以在此处找到更多信息:Pandas replace rare values