web-dev-qa-db-ja.com

データフレーム列のすべての値が同じかどうかを確認します

countsのすべての列の値がデータフレームで同じであるかどうかをすばやく簡単に確認したい:

に:

_import pandas as pd

d = {'names': ['Jim', 'Ted', 'Mal', 'Ted'], 'counts': [3, 4, 3, 3]}
pd.DataFrame(data=d)
_

アウト:

_  names  counts
0   Jim       3
1   Ted       4
2   Mal       3
3   Ted       3
_

_if all counts = same value_、次にprint('True')という単純な条件が必要です。

これを行う高速な方法はありますか?

15
HelloToEarth

これを行う効率的な方法は、最初の値を残りの値と比較し、 all を使用することです。

def is_unique(s):
    a = s.to_numpy() # s.values (pandas<0.24)
    return (a[0] == a[1:]).all()

is_unique(df['counts'])
# False

データフレーム全体

データフレーム全体で同じタスクを実行したい場合は、allaxis=0を設定して上記を拡張できます。

def unique_cols(df):
    a = df.to_numpy() # df.values (pandas<0.24)
    return (a[0] == a[1:]).all(0)

nuniquepd.Seriesの場合)など、他のいくつかのアプローチと比較した上記の方法のベンチマークは次のとおりです。

s_num = pd.Series(np.random.randint(0, 1_000, 1_100_000))

perfplot.show(
    setup=lambda n: s_num.iloc[:int(n)], 

    kernels=[
        lambda s: s.nunique() == 1,
        lambda s: is_unique(s)
    ],

    labels=['nunique', 'first_vs_rest'],
    n_range=[2**k for k in range(0, 20)],
    xlabel='N'
)

enter image description here


pd.DataFrameの場合、特に短いオプションを利用できるため、numbaも良いオプションです。 -特定の列に繰り返し値が表示されるとすぐに切り取ります(これは数値データでのみ機能します):

from numba import njit

@njit
def unique_cols_nb(a):
    n_cols = a.shape[1]
    out = np.zeros(n_cols, dtype=np.int8)
    for i in range(n_cols):
        init = a[0, i]
        for j in a[1:, i]:
            if j != init:
                break
        else:
            out[i] = 1
    return out

3つの方法を比較すると、

df = pd.DataFrame(np.concatenate([np.random.randint(0, 1_000, (500_000, 200)), 
                                  np.zeros((500_000, 10))], axis=1))

perfplot.show(
    setup=lambda n: df.iloc[:int(n),:], 

    kernels=[
        lambda df: (df.nunique(0) == 1).values,
        lambda df: unique_cols_nb(df.values).astype(bool),
        lambda df: unique_cols(df) 
    ],

    labels=['nunique', 'unique_cols_nb', 'unique_cols'],
    n_range=[2**k for k in range(0, 20)],
    xlabel='N'
)

enter image description here

20
yatu

np.uniqueを使用して更新

len(np.unique(df.counts))==1
False

または

len(set(df.counts.tolist()))==1

または

df.counts.eq(df.counts.iloc[0]).all()
False

または

df.counts.std()==0
False
4
YOBEN_S

nuniqueは必要以上に多くの作業を行うと思います。反復は最初の違いで停止できます。このシンプルで汎用的なソリューションはitertoolsを使用します:

import itertools

def all_equal(iterable):
    "Returns True if all elements are equal to each other"
    g = itertools.groupby(iterable)
    return next(g, True) and not next(g, False)

all_equal(df.counts)

これを使用して、一定の内容を持つall列を一度に見つけることもできます。

constant_columns = df.columns[df.apply(all_equal)]

少し読みやすくはありますが、パフォーマンスが低下します:

df.counts.min() == df.counts.max()

追加 skipna=False必要に応じてここに。

0