代码之家  ›  专栏  ›  技术社区  ›  mortysporty

对于带有NAN的列,行最小值()和最大值()失败

  •  7
  • mortysporty  · 技术社区  · 7 年前

    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 回复  |  直到 5 年前
        1
  •  9
  •   juanpa.arrivillaga    7 年前

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

    >>> 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]
    
        2
  •  6
  •   cs95 abhishek58g    7 年前

    这种情况似乎发生在 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
    

    如果手动将标志设置为false,这将正确引发 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()
    

    . 作为一种解决方法,转换为 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
    

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

    juan suggests ,您可以向 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]
    
        3
  •  1
  •   FabienP    7 年前

    以下各项应起作用:

    >>> 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() 计算包含no的行的掩码 np.nan
    2. df_nan.where() 将前一个掩码应用于数据帧
    3. .max(axis=1) 获取行最大值

    None . 它允许通过不显示最大值来跟踪缺少值的行。

    NaN NaT 是你想要的。