Я пытаюсь взять по очереди максимум (и мин) из двух столбцов, содержащих даты
from datetime import date
import pandas as pd
import numpy as np
df = pd.DataFrame({'date_a' : [date(2015, 1, 1), date(2012, 6, 1),
date(2013, 1, 1), date(2016, 6, 1)],
'date_b' : [date(2012, 7, 1), date(2013, 1, 1),
date(2014, 3, 1), date(2013, 4, 1)]})
df[['date_a', 'date_b']].max(axis=1)
Out[46]:
0 2015-01-01
1 2013-01-01
2 2014-03-01
3 2016-06-01
Как и ожидалось. Однако если в фрейме данных содержится одно значение NaN, вся операция завершается неудачно
df_nan = pd.DataFrame({'date_a' : [date(2015, 1, 1), date(2012, 6, 1),
np.NaN, date(2016, 6, 1)],
'date_b' : [date(2012, 7, 1), date(2013, 1, 1),
date(2014, 3, 1), date(2013, 4, 1)]})
df_nan[['date_a', 'date_b']].max(axis=1)
Out[49]:
0 NaN
1 NaN
2 NaN
3 NaN
dtype: float64
Что здесь происходит? Я ожидал этого результата
0 2015-01-01
1 2013-01-01
2 NaN
3 2016-06-01
Как этого добиться?
3 ответа
Я бы сказал, что лучшее решение - использовать соответствующий dtype
. Pandas предоставляет очень хорошо интегрированный datetime
dtype
. Обратите внимание, вы используете object
dtypes ...
>>> df
date_a date_b
0 2015-01-01 2012-07-01
1 2012-06-01 2013-01-01
2 NaN 2014-03-01
3 2016-06-01 2013-04-01
>>> df.dtypes
date_a object
date_b object
dtype: object
Но обратите внимание, проблема исчезает при использовании
>>> df2 = df.apply(pd.to_datetime)
>>> df2
date_a date_b
0 2015-01-01 2012-07-01
1 2012-06-01 2013-01-01
2 NaT 2014-03-01
3 2016-06-01 2013-04-01
>>> df2.min(axis=1)
0 2012-07-01
1 2012-06-01
2 2014-03-01
3 2013-04-01
dtype: datetime64[ns]
Похоже, это происходит, когда объекты date
смешиваются с плавающей точкой (например, NaN
) в столбцах. По умолчанию флаг numeric_only
устанавливается из-за единственного значения с плавающей запятой. Например, замените ваш df_nan
следующим:
df_float = pd.DataFrame({'date_a' : [date(2015, 1, 1), date(2012, 6, 1),
1.023, date(2016, 6, 1)],
'date_b' : [date(2012, 7, 1), 3.14,
date(2014, 3, 1), date(2013, 4, 1)]})
print(df_float.max(1))
0 NaN
1 NaN
2 NaN
3 NaN
dtype: float64
Если для флага вручную установлено значение «ложь», это приведет к правильному выбрасыванию TypeError
, потому что:
print(date(2015, 1, 1) < 1.0)
TypeError Traceback (most recent call last)
<ipython-input-362-ccbf44ddb40a> in <module>()
1
----> 2 print(date(2015, 1, 1) < 1.0)
TypeError: unorderable types: datetime.date() < float()
Тем не менее, панды, кажется, принуждают все к NaN
. Как обходной путь, преобразование в str
с использованием df.astype
, кажется, делает это:
out = df_nan.astype(str).max(1)
print(out)
0 2015-01-01
1 2013-01-01
2 nan
3 2016-06-01
dtype: object
В этом случае сортировка лексикографически дает то же решение, что и раньше.
В противном случае, как Хуан предлагает вы можете привести к datetime
используя pd.to_datetime
:
out = df_nan.apply(pd.to_datetime, errors='coerce').max(1)
print(out)
0 2015-01-01
1 2013-01-01
2 2014-03-01
3 2016-06-01
dtype: datetime64[ns]
Следующее должно работать:
>>> df_nan.where(df_nan.T.notnull().all()).max(axis=1)
Out[1]:
0 2015-01-01
1 2013-01-01
2 None
3 2016-06-01
dtype: object
Куда:
df_nan.T.notnull().all()
вычисляет маску строки, не содержащейnp.nan
df_nan.where()
применяет прежнюю маску к кадру данных.max(axis=1)
получает построчный максимум
Это работает, потому что максимум массива, где все значения np.nan
, равен None
. Это позволяет отслеживать строки, в которых отсутствует значение, не показывая максимум.
Но это решение остается за вами, в противном случае вам нужно решение @ juanpa.arrivillaga, которое преобразует NaN
в NaT
.
Похожие вопросы
Новые вопросы
python
Python - это многопарадигмальный, динамически типизированный, многоцелевой язык программирования. Он разработан для быстрого изучения, понимания и использования, а также для обеспечения чистого и единообразного синтаксиса. Обратите внимание, что Python 2 официально не поддерживается с 01.01.2020. Тем не менее, для вопросов о Python, связанных с версией, добавьте тег [python-2.7] или [python-3.x]. При использовании варианта Python (например, Jython, PyPy) или библиотеки (например, Pandas и NumPy) включите его в теги.