У меня есть проблема, и я не могу найти никакого решения в Интернете или документации, даже если я думаю, что это очень тривиально.
Что я хочу сделать?
У меня есть такой фрейм
CLASS FEATURE1 FEATURE2 FEATURE3
X A NaN NaN
X NaN A NaN
B A A A
Я хочу сгруппировать по метке (CLASS) и отобразить количество NaN-значений, которые учитываются в каждой функции, чтобы она выглядела следующим образом. Цель этого - получить общее представление о том, как пропущенные значения распределены по различным классам.
CLASS FEATURE1 FEATURE2 FEATURE3
X 1 1 2
B 0 0 0
Я знаю, как получить количество df.groupby['CLASS'].count()
значений - df.groupby['CLASS'].count()
Есть ли что-то подобное для NaN-значений?
Я пытался вычесть count() из size(), но он вернул неформатированный вывод, заполненный значением NaN
Ответ 1
Вычислите маску с 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- й оси для вычитания с выравниванием по индексу:
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)
Фактическая производительность зависит от ваших данных и настроек, поэтому пробег может отличаться.
Ответ 2
Вы можете использовать set_index
и sum
:
df.set_index('CLASS').isna().sum(level=0)
Выход:
FEATURE1 FEATURE2 FEATURE3
CLASS
X 1.0 1.0 2.0
B 0.0 0.0 0.0
Ответ 3
Использование разницы между count
и size
g=df.groupby('CLASS')
-g.count().sub(g.size(),0)
FEATURE1 FEATURE2 FEATURE3
CLASS
B 0 0 0
X 1 1 2
И мы можем преобразовать этот вопрос в более общий вопрос, как посчитать, сколько NaN
в цикле данных с циклом for
pd.DataFrame({x: y.isna().sum()for x , y in g }).T.drop('CLASS',1)
Out[468]:
FEATURE1 FEATURE2 FEATURE3
B 0 0 0
X 1 1 2