【问题标题】:Ignoring NaNs with str.contains使用 str.contains 忽略 NaN
【发布时间】:2015-04-03 09:37:28
【问题描述】:

我想查找包含字符串的行,如下所示:

DF[DF.col.str.contains("foo")]

但是,这会失败,因为某些元素是 NaN:

ValueError: 无法使用包含 NA / NaN 值的向量进行索引

所以我求助于混淆

DF[DF.col.notnull()][DF.col.dropna().str.contains("foo")]

有没有更好的办法?

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    有一个标志:

    In [11]: df = pd.DataFrame([["foo1"], ["foo2"], ["bar"], [np.nan]], columns=['a'])
    
    In [12]: df.a.str.contains("foo")
    Out[12]:
    0     True
    1     True
    2    False
    3      NaN
    Name: a, dtype: object
    
    In [13]: df.a.str.contains("foo", na=False)
    Out[13]:
    0     True
    1     True
    2    False
    3    False
    Name: a, dtype: bool
    

    请参阅str.replace 文档:

    na : 默认 NaN,缺失值的填充值。


    因此您可以执行以下操作:

    In [21]: df.loc[df.a.str.contains("foo", na=False)]
    Out[21]:
          a
    0  foo1
    1  foo2
    

    【讨论】:

    • 在这里,我遇到了一种情况,a 是从 CSV 填充的,a 列包含字符串“nan”。 pandas“智能”将其转换为NaN,并在我尝试执行df.a.str.contains() 时开始抱怨。所以是的protip:确保在read_csv() 中设置列​​类型,或者之后执行df = df.where(pandas.notnull(df), "nan") 之类的操作 LOL
    • 你救了我...如果这不在这里,我想我会经历两周的噩梦,把我的头撞到墙上:-) 绝对值得+1,哈哈
    • 大声笑为什么不是这个默认值?
    • 宾果游戏。这应该是默认标志!
    • 希望 na 提供其他 str 函数,例如 str.extract()。
    【解决方案2】:
    import folium
    import pandas
    
    data= pandas.read_csv("maps.txt")
    
    lat = list(data["latitude"])
    lon = list(data["longitude"])
    
    map= folium.Map(location=[31.5204, 74.3587], zoom_start=6, tiles="Mapbox Bright")
    
    fg = folium.FeatureGroup(name="My Map")
    
    for lt, ln in zip(lat, lon):
    c1 = fg.add_child(folium.Marker(location=[lt, ln], popup="Hi i am a Country",icon=folium.Icon(color='green')))
    
    child = fg.add_child(folium.Marker(location=[31.5204, 74.5387], popup="Welcome to Lahore", icon= folium.Icon(color='green')))
    
    map.add_child(fg)
    
    map.save("Lahore.html")
    
    
    Traceback (most recent call last):
      File "C:\Users\Ryan\AppData\Local\Programs\Python\Python36-32\check2.py", line 14, in <module>
        c1 = fg.add_child(folium.Marker(location=[lt, ln], popup="Hi i am a Country",icon=folium.Icon(color='green')))
      File "C:\Users\Ryan\AppData\Local\Programs\Python\Python36-32\lib\site-packages\folium\map.py", line 647, in __init__
        self.location = _validate_coordinates(location)
      File "C:\Users\Ryan\AppData\Local\Programs\Python\Python36-32\lib\site-packages\folium\utilities.py", line 48, in _validate_coordinates
        'got:\n{!r}'.format(coordinates))
    ValueError: Location values cannot contain NaNs, got:
    [nan, nan]
    

    【讨论】:

    • 这不是答案。
    【解决方案3】:

    除了以上答案,我想说对于没有单个单词名称的列,您可以使用:-

    df[df['Product ID'].str.contains("foo") == True]
    

    希望这会有所帮助。

    【讨论】:

      【解决方案4】:

      我不是 100% 知道为什么(实际上是来这里寻找答案),但这也有效,并且不需要替换所有 nan 值。

      import pandas as pd
      import numpy as np
      
      df = pd.DataFrame([["foo1"], ["foo2"], ["bar"], [np.nan]], columns=['a'])
      
      newdf = df.loc[df['a'].str.contains('foo') == True]
      

      使用或不使用.loc

      我不知道为什么会这样,因为我理解当您使用括号进行索引时,pandas 会将括号内的任何内容评估为TrueFalse。我不知道为什么让括号内的短语“extra boolean”有任何效果。

      【讨论】:

        【解决方案5】:

        你也可以模仿:

        DF[DF.col.str.contains(pat = '(foo)', regex = True) ]
        

        【讨论】:

          【解决方案6】:
          df[df.col.str.contains("foo").fillna(False)]
          

          【讨论】:

            【解决方案7】:

            您也可以使用query方法通过布尔表达式查询DataFrame的列,如下所示:

            df.query('a.str.contains("foo", na=False)')
            

            请注意,您可能不会获得性能改进,但它更具可读性(可以说)。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2018-07-05
              • 2019-09-24
              • 2019-08-30
              • 2021-06-15
              • 1970-01-01
              • 1970-01-01
              • 2021-11-15
              相关资源
              最近更新 更多