首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Rowwise min()和max()对于带有NaNs的列失败

Rowwise min()和max()对于带有NaNs的列失败
EN

Stack Overflow用户
提问于 2017-08-26 20:18:34
回答 3查看 2.9K关注 0票数 7

我试图取包含日期的两列的最大行数(和最小值)。

代码语言:javascript
运行
复制
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值,则整个操作将失败。

代码语言:javascript
运行
复制
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

这里发生什么事情?我正期待着这个结果

代码语言:javascript
运行
复制
0    2015-01-01
1    2013-01-01
2    NaN
3    2016-06-01

如何才能做到这一点?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-08-26 20:35:08

我认为最好的解决方案是使用适当的dtype。熊猫提供了一个非常完整的datetime dtype。所以请注意,您使用的是object类型..。

代码语言:javascript
运行
复制
>>> 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

但是请注意,当您使用

代码语言:javascript
运行
复制
>>> 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]
票数 9
EN

Stack Overflow用户

发布于 2017-08-26 20:25:22

date对象与列中的浮点数(如NaN)混合时,似乎会发生这种情况。默认情况下,numeric_only标志是由于单个浮动值而设置的。例如,将您的df_nan替换为:

代码语言:javascript
运行
复制
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

如果该标志被手动设置为false,这将正确地抛出一个TypeError,因为:

代码语言:javascript
运行
复制
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似乎可以做到这一点:

代码语言:javascript
运行
复制
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

在这种情况下,按字典顺序排序会产生与以前相同的解决方案。

否则,作为juan suggests,您可以使用pd.to_datetime转换为datetime

代码语言:javascript
运行
复制
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]
票数 6
EN

Stack Overflow用户

发布于 2017-08-26 21:19:40

下列措施应能发挥作用:

代码语言:javascript
运行
复制
>>> 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

其中:

  1. df_nan.T.notnull().all()计算不包含np.nan的行掩码。
  2. df_nan.where()将前一个掩码应用于数据帧
  3. .max(axis=1)获得逐行最大值。

这是因为所有值都是np.nan的数组的最大值是None。它允许通过不显示最大值来跟踪值丢失的行。

但是这个决定取决于您,否则@juanpa.arrivillaga将NaN转换为NaT的解决方案就是您想要的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45899340

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档