【发布时间】:2020-07-21 04:12:48
【问题描述】:
我需要找到 pandas groupby 对象或单个系列的模式/最常见元素,为此我有以下功能:
def get_most_common(srs):
from collections import Counter
import numpy as np
x = list(srs)
my_counter = Counter(x)
if np.nan not in my_counter.keys():
most_common_value = my_counter.most_common(1)[0][0]
else:
most_common_value = srs.mode(dropna=False).iloc[0]
return most_common_value
如果是平局,我不在乎选择哪一个——随机就可以了。
Counter 在没有 NaN 时更快,但在使用 NaN 时会给出错误的结果。 pd.Series.mode 总是正确的,但是当没有 NaN 时它比 Counter 慢。这是一场赌博(当没有 NaN 时速度更快,但由于额外检查 np.nan not in my_counter.keys() 而在有 NaN 时速度较慢)。到目前为止,我的大型数据集的性能令人满意,可能是因为很多情况下没有 NaN。但是有没有办法让它更快?
【问题讨论】:
-
在这种情况下,您真的不需要 if/else 和
Counter。不管np.nan是否在您的Series中,您总是要求最常见的值,它可以是np.nan。不用定义get_most_common,只需使用srs.mode(dropna=False),你会得到同样的结果。 -
您能否在进行 groupby 之前使用原始数据中没有的值(例如 max + 1 或类似的值)填充,然后仅使用
Counter?如果这个值是 return 你知道它是 nan? -
@r.ook 我尝试专门使用
srs.mode(dropna=False)。它比我上面做的要慢得多。 -
@Ben.T 是的,我尝试过类似
srs.fillna('NAN')的操作,使用Counter,然后如果我得到'NAN'作为模式,我会将其恢复为np.nan。我在一个带有 timeit 的示例系列上尝试了这个(不是在大型数据集上),它似乎比我上面的函数慢,即使系列中没有 NaN。 -
@Ben.T,系列元素是字符串。我发现用 0 填充比用字符串填充要好,但是从 timeit 来看,具有 NaN 的系列和没有 NaN 的系列的性能似乎同样慢。我上面的函数在没有 NaN 的情况下工作得更好(几乎和单独的
Counter一样快),这似乎就是为什么它适用于大型数据集。