【问题标题】:Compare Series containing None比较包含无的系列
【发布时间】:2018-01-26 00:32:19
【问题描述】:

我正在使用 python shift 函数来比较 Series 中的值是否等于先前的值。基本上

import pandas as pd

a = pd.Series([2, 2, 4, 5])

a == a.shift()
Out[1]: 
0    False
1     True
2    False
3    False
dtype: bool

这符合预期。 (第一个比较是 False,因为我们正在与移位系列的NA 进行比较)。现在,我确实有我没有任何价值的系列,即。 None,像这样

b = pd.Series([None, None, 4, 5])

这里两个Nones的比较得到False

b == b.shift()
Out[3]: 
0    False
1    False
2    False
3    False
dtype: bool

我愿意接受某种哲学推理,认为比较 None 是没有意义的等等,但是

c = None
d = None
c == d
Out[4]: True

这是怎么回事?!

而且,我真正想知道的是;鉴于我希望它将None 视为平等,我如何对我的b 系列进行比较?那就是我希望b == b.shift() 给出与a == a.shift() 相同的结果。

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    here 所示,None 与在 Pandas/numpy 中不相等的 nan 进行比较。

    但是对于 None,您可以使用 apply 轻松获得一个不错的解决方案:

    In[1]:
    foo = pd.Series([None, 'a'])
    foo==None
    
    Out[1]:
    0    False
    1    False
    dtype: bool 
    
    
    In[2]:
    foo.apply(lambda a:a==None)
    Out[2]: 
    0     True
    1    False
    dtype: bool
    

    【讨论】:

      【解决方案2】:

      如果您可以定期比较相邻条目(即,将最后一个条目与第一个条目进行比较),那么还有另一个使用 numpy roll 函数的简单解决方案:

      import numpy as np
      
      b = [None, None, 4, 5] 
      # or list(b) if b is a pandas Series
      
      np.roll(b,1) == b
      

      返回:

      > array([False,  True, False, False])
      

      【讨论】:

      • 有趣!谢谢。由于某种原因,它似乎不适用于熊猫系列:|
      【解决方案3】:

      None 被强制转换为 NaNNaN 具有不等于自身的属性:

      [54]:
      b = pd.Series([None, None, 4, 5])
      b
      
      Out[54]: 
      0    NaN
      1    NaN
      2    4.0
      3    5.0
      dtype: float64
      

      如您所见:

      In[55]:
      b==b
      
      Out[55]: 
      0    False
      1    False
      2     True
      3     True
      dtype: bool
      

      我不知道你怎样才能让它正常工作,虽然这可行:

      In[68]:
      ( (b == b.shift())  | ( (b != b.shift()) &  (b != b) ) )
      
      Out[68]: 
      0     True
      1     True
      2    False
      3    False
      dtype: bool
      

      你会得到第一行的错误结果,因为当你 shift 向下时,你正在与一个不存在的行进行比较:

      In[69]:
      b.shift()
      
      Out[69]: 
      0    NaN
      1    NaN
      2    NaN
      3    4.0
      dtype: float64
      

      所以NaN 正在比较布尔逻辑中的True,因为第一行是NaN,移位系列的第一行也是如此。

      要解决第一行误报问题,您可以对结果结果进行切片以忽略第一行:

      In[70]:
      ( (b == b.shift())  | ( (b != b.shift()) &  (b != b) ) )[1:]
      
      Out[70]: 
      1     True
      2    False
      3    False
      dtype: bool
      

      至于为什么会被强制转换,Pandas 试图将数据强制转换为兼容的 numpy,这里选择了 float,因为 ints 和 None 值,NoneNaN 无法表示ints

      要获得与示例中的a 相同的结果,您应该将第一行覆盖为False,因为它总是会失败:

      In[78]:
      result = pd.Series( ( (b == b.shift())  | ( (b != b.shift()) &  (b != b) ) ) )
      result.iloc[0] = False
      result
      
      Out[78]: 
      0    False
      1     True
      2    False
      3    False
      dtype: bool
      

      【讨论】:

      • 对于有兴趣了解其工作原理的各方,请参阅stackoverflow.com/questions/44864912/…
      • 关于 NaN 和布尔逻辑的另一个很好的 SO。 stackoverflow.com/questions/43925797/…
      • 啊哈! :) 谢谢。对问题的最后一部分有什么想法吗?我真的不想介绍像 999 或类似的假人
      • 你可能想对系列进行切片,这样你可能会忽略第一行,我会更新
      • 稍后我会试一试(目前正在通勤:))如果有效,请将您的回复标记为答案!
      猜你喜欢
      • 2022-01-08
      • 2017-01-03
      • 1970-01-01
      • 1970-01-01
      • 2012-01-06
      • 1970-01-01
      • 2013-08-29
      • 1970-01-01
      相关资源
      最近更新 更多