Странное поведение с медианами панд

Рассмотрим следующий кадр данных:

       b           c     d     e  f     g     h
0   6.25  2018-04-01  True   NaN  7  54.0  64.0
1  32.50  2018-04-01  True   NaN  7  54.0  64.0
2  16.75  2018-04-01  True   NaN  7  54.0  64.0
3  29.25  2018-04-01  True   NaN  7  54.0  64.0
4  21.75  2018-04-01  True   NaN  7  54.0  64.0
5  21.75  2018-04-01  True  True  7  54.0  64.0
6   7.75  2018-04-01  True  True  7  54.0  64.0
7  23.25  2018-04-01  True  True  7  54.0  64.0
8  12.25  2018-04-01  True  True  7  54.0  64.0
9  30.50  2018-04-01  True   NaN  7  54.0  64.0

(скопируйте и вставьте и используйте df = pd.read_clipboard() для создания кадра данных)

Поиск медианы изначально работает без проблем:

df.median()

b    21.75
d     1.00
e     1.00
f     7.00
g    54.00
h    64.00
dtype: float64

Однако, если столбец отброшен, а затем median найдена, медиана для столбца e исчезает:

new_df = df.drop(columns=['b'])
new_df.median()

d     1.0
f     7.0
g    54.0
h    64.0
dtype: float64

Это поведение немного неожиданно, и поиск медианы для столбца e сам по себе все еще работает:

new_df['e'].median()
1.0

Использование skipna=False не имеет значения:

new_df.median(skipna=False)

d     1.0
f     7.0
g    54.0
h    64.0
dtype: float64

(это относится к исходному фрейму данных):

df.median(skipna=False)

b    21.75
d     1.00
e      NaN
f     7.00
g    54.00
h    64.00
dtype: float64

Тип данных столбца e является object как в df и в new_df и единственное различие между new_df двумя new_df заключается в том, что new_df не имеет столбца b. Добавление столбца обратно в new_df не new_df проблему. Это происходит только тогда, когда первый столбец b опущен. Это не происходит, если столбец e является типом данных с плавающей запятой или целым числом.

Такое поведение присутствует как в pandas==0.22.0 и в pandas==0.24.1

Теперь есть открытая проблема GitHub для всех, чтобы попытаться решить эту проблему!

Ответ 1

Это похоже на ошибку. Когда мы отправляем любой df в median, это сопоставляется с внутренней функцией _reduce. Если для numeric_only установлено значение None, это вычисляет медиану по рядам и игнорирует сбои (для столбцов c, например, для вычисления медианы не удастся.) И накапливает результаты (см. _reduce в pandas source core/frame.py). Пока все хорошо. Но при объединении результатов вместе он проверяет, являются ли результаты скалярными или последовательными (для median конечно, это будет скаляр). Для этого всегда используйте первый столбец (см. wrap_results в исходном ядре pandas/apply.py). Таким образом, если первый столбец calc завершился неудачно и он был пропущен, эта проверка завершится неудачно, что вызовет исключение. Это запускает резервный метод в пределах _reduce для принудительного _reduce данных только в числовой _reduce (отбрасывание любых столбцов с NaN) и повторное вычисление медиан.

Таким образом, в вашем случае, если столбец c (или любой другой тип d, где вычисление медианы не удастся, например, текст) находится в первом столбце, тогда все столбцы с NaN также будут удалены для медианных результатов. Настройка skipna не меняется, так как ошибка заключается в том, что нецифровый столбец в первой позиции запускает принудительное вычисление только чисел. Я не вижу возможного исправления без исправления в базе кодов панд. Или обеспечение первого столбца всегда будет успешным для вычисления медианы.