Вычислите маску с помощью isna
, затем сгруппируйте и найдите сумму:
df.drop('CLASS', 1).isna().groupby(df.CLASS, sort=False).sum().reset_index()
CLASS FEATURE1 FEATURE2 FEATURE3
0 X 1.0 1.0 2.0
1 B 0.0 0.0 0.0
Другой вариант - вычесть size
из count
, используя rsub
вдоль0 th ось для вычитания, выровненного по индексу:
df.groupby('CLASS').count().rsub(df.groupby('CLASS').size(), axis=0)
Или
g = df.groupby('CLASS')
g.count().rsub(g.size(), axis=0)
FEATURE1 FEATURE2 FEATURE3
CLASS
B 0 0 0
X 1 1 2
Есть довольноНесколько хороших ответов, поэтому вот несколько timeits
для вашего прочтения:
df_ = df
df = pd.concat([df_] * 10000)
%timeit df.drop('CLASS', 1).isna().groupby(df.CLASS, sort=False).sum()
%timeit df.set_index('CLASS').isna().sum(level=0)
%%timeit
g = df.groupby('CLASS')
g.count().rsub(g.size(), axis=0)
11.8 ms ± 108 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
9.47 ms ± 379 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
6.54 ms ± 81.6 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
Фактическая производительность зависит от ваших данных и настроек, поэтому ваш пробег может отличаться.