簡體   English   中英

獲得具有 NaN 的 pandas 系列模式的最快方法

[英]Fastest way to get the mode of a pandas Series with NaN

我需要通過 object 或單個系列找到 pandas 組的模式/最常見元素,為此我有以下 function:

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

在平局的情況下,我不在乎選擇哪一個——隨機就可以了。

當沒有 NaN 時, Counter會更快,但使用 NaN 時會給出錯誤的結果。 pd.Series.mode總是正確的,但是當沒有 NaN 時它比Counter慢。 這是一場賭博(沒有 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是 2 x 50000 行DataFrame的隨機 2 位字符串,從099 ,其中has_nanmodenan=551


如果有的話,您的if np.nan not in my_counter.keys()條件將始終被觸發,因為np.nan不在my_counter.keys()中。 所以實際上你從來沒有使用pd.Series.mode ,它總是在使用Counter 如另一個問題所述,由於您的pandas object 已經在Series/DataFrame中創建了np.nan的副本,因此永遠不會滿足in條件。 試試看:

np.nan in pd.Series([np.nan, 1, 2]).to_list()
# False

消除if/else的全部復雜性並堅持使用一種方法。 然后比較性能。 正如您在另一個問題中提到的,pandas 方法幾乎總是比任何外部模塊/方法更好的方法。 如果您仍在觀察其他情況,請更新您的問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM