我需要找到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
总是正确的,但是比Counter
没有NaN时要慢。这是一场赌博(由于没有额外的检查,在没有NaN时速度更快,而在没有NaN时速度更快np.nan not in my_counter.keys()
)。到目前为止,我的大型数据集获得了令人满意的性能,这可能是因为在许多情况下都没有NaN。但是有没有办法使它更快呢?
我发现使用会获得更好的性能,这很奇怪Counter
。这是我的测试结果(n=10000
):
Using Series.mode on Series with nan: 52.41649858
Using Series.mode on Series without nan: 17.186453438
Using Counter on Series with nan: 269.33117825500005
Using Counter on Series without nan: 134.207576572
#-----------------------------------------------------#
Series.mode Counter
----------- -------------
With nan 52.42s 269.33s
Without nan 17.19s 134.21s
测试代码:
import timeit
setup = '''
import pandas as pd
from collections import Counter
def get_most_common(srs):
return srs.mode(dropna=False)[0]
def get_most_common_counter(srs):
x = list(srs)
my_counter = Counter(x)
return my_counter.most_common(1)[0][0]
df = pd.read_csv(r'large.data')
'''
print(f"""Using Series.mode on Series with nan: {timeit.timeit('get_most_common(df["has_nan"])', setup=setup, number=10000)}""")
print(f"""Using Series.mode on Series without nan: {timeit.timeit('get_most_common(df["no_nan"])', setup=setup, number=10000)}""")
print(f"""Using Counter on Series with nan: {timeit.timeit('get_most_common_counter(df["has_nan"])', setup=setup, number=10000)}""")
print(f"""Using Counter on Series without nan: {timeit.timeit('get_most_common_counter(df["no_nan"])', setup=setup, number=10000)}""")
large.data
是DataFrame
从0
到的2 x 50000行随机2位数字符串99
,其中has_nan
具有mode
的nan=551
。
如果有的话,您的if np.nan not in my_counter.keys()
条件将始终被触发,因为np.nan
不在中my_counter.keys()
。因此,实际上您从未使用过pd.Series.mode
,它一直在使用Counter
。正如在其他问题中提到的,因为你的pandas
对象已经创建的副本np.nan
内Series/DataFrame
,该in
条件将永远不会实现。试试看:
np.nan in pd.Series([np.nan, 1, 2]).to_list()
# False
消除整个过程的复杂性,if/else
并坚持使用一种方法。然后比较性能。正如您在其他问题中提到的那样,与任何外部模块/方法相比,大熊猫方法几乎总是更好的方法。如果您仍在观察,请更新您的问题。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句