【问题标题】:pandas combine two columns with null values熊猫将两列与空值结合起来
【发布时间】:2017-05-17 21:38:58
【问题描述】:

我有一个包含两列的 df,我想合并两列而忽略 NaN 值。问题是有时两列都有 NaN 值,在这种情况下,我希望新列也有 NaN。示例如下:

df = pd.DataFrame({'foodstuff':['apple-martini', 'apple-pie', None, None, None], 'type':[None, None, 'strawberry-tart', 'dessert', None]})

df
Out[10]:
foodstuff   type
0   apple-martini   None
1   apple-pie   None
2   None    strawberry-tart
3   None    dessert
4   None    None

我尝试使用fillna 来解决这个问题:

df['foodstuff'].fillna('') + df['type'].fillna('')

我得到了:

0      apple-martini
1          apple-pie
2    strawberry-tart
3            dessert
4                   
dtype: object

第 4 行已成为空白值。在这种情况下我不想要的是 NaN 值,因为两个组合列都是 NaN。

0      apple-martini
1          apple-pie
2    strawberry-tart
3            dessert
4            None       
dtype: object

【问题讨论】:

    标签: python pandas dataframe nonetype


    【解决方案1】:

    如果您处理的列包含其他列不包含的内容,反之亦然,则可以完成这项工作的单行列

    >>> df.rename(columns={'type': 'foodstuff'}).stack().unstack()
             foodstuff
    0    apple-martini
    1        apple-pie
    2  strawberry-tart
    3          dessert
    

    ...如果您有多个要“复杂”的列,则该解决方案也可以很好地概括,只要您可以定义 ~.rename 映射。这种重命名的目的是创建~.stack().unstack() 将为您处理的重复项。

    如上所述,此解决方案仅适用于具有正交列的配置,即从不同时被赋值的列。

    【讨论】:

    • 在我的情况下 pd.DataFrame.stack() 进行列组合。 unstack 取消组合。
    【解决方案2】:

    我们可以让这个问题更加完整,并为这类问题提供一个通用的解决方案。

    其中的关键是我们希望将一组列连接在一起,但忽略NaNs。

    这是我的答案:

    df = pd.DataFrame({'foodstuff':['apple-martini', 'apple-pie', None, None, None], 
                   'type':[None, None, 'strawberry-tart', 'dessert', None],
                  'type1':[98324, None, None, 'banan', None],
                  'type2':[3, None, 'strawberry-tart', np.nan, None]})
    

    df=df.fillna("NAN")
    df=df.astype('str')
    df["output"] = df[['foodstuff', 'type', 'type1', 'type2']].agg(', '.join, axis=1)
    df['output'] = df['output'].str.replace('NAN, ', '')
    df['output'] = df['output'].str.replace(', NAN', '')
    

    【讨论】:

      【解决方案3】:
      1. 您可以将非零值替换为列名,例如

        df1= df.replace(1, pd.Series(df.columns, df.columns))

      2. 用空字符串替换 0,然后像下面这样合并列

        f = f.replace(0, '') f['new'] = f.First+f.Second+f.Three+f.Four

      请参阅下面的完整代码。

      import pandas as pd
      df = pd.DataFrame({'Second':[0,1,0,0],'First':[1,0,0,0],'Three':[0,0,1,0],'Four':[0,0,0,1], 'cl': ['3D', 'Wireless','Accounting','cisco']})
      df2=pd.DataFrame({'pi':['Accounting','cisco','3D','Wireless']})
      df1= df.replace(1, pd.Series(df.columns, df.columns))
      f = pd.merge(df1,df2,how='right',left_on=['cl'],right_on=['pi'])
      f = f.replace(0, '')
      f['new'] = f.First+f.Second+f.Three+f.Four
      

      df1:

      In [3]: df1                                                                                                                                                                              
      Out[3]: 
         Second  First  Three  Four          cl
      0       0  First      0     0          3D
      1  Second      0      0     0    Wireless
      2       0      0  Three     0  Accounting
      3       0      0      0  Four       cisco
      

      df2:

      In [4]: df2                                                                                                                                                                              
      Out[4]: 
                 pi
      0  Accounting
      1       cisco
      2          3D
      3    Wireless
      

      最终的 df 将是:

      In [2]: f                                                                                                                                                                                
      Out[2]: 
         Second  First  Three  Four          cl          pi     new
      0          First                       3D          3D   First
      1  Second                        Wireless    Wireless  Second
      2                 Three        Accounting  Accounting   Three
      3                        Four       cisco       cisco    Four
      

      【讨论】:

        【解决方案4】:

        您可以将combine 方法与lambda 一起使用:

        df['foodstuff'].combine(df['type'], lambda a, b: ((a or "") + (b or "")) or None, None)
        

        (a or "") 如果 a 是 None,则返回 "",然后将相同的逻辑应用于串联(如果串联为空字符串,则结果将为 None)。

        【讨论】:

          【解决方案5】:
          • fillna 两列一起
          • sum(1) 添加他们
          • replace('', np.nan)

          df.fillna('').sum(1).replace('', np.nan)
          
          0      apple-martini
          1          apple-pie
          2    strawberry-tart
          3            dessert
          4                NaN
          dtype: object
          

          【讨论】:

            【解决方案6】:

            在一列上使用fillna,另一列是填充值:

            df['foodstuff'].fillna(df['type'])
            

            结果输出:

            0      apple-martini
            1          apple-pie
            2    strawberry-tart
            3            dessert
            4               None
            

            【讨论】:

            • 这只是因为提供了一个相当不切实际的例子,其中每行总是至少有一个 None。
            • @kilgoretrout 我发现即使两列都包含空值也可以工作
            • 是否有任何选项可以删除同一行中fillna 之后的'type 列。?即通过避免另一个'drop`语句
            【解决方案7】:

            你总是可以用 None 填充新列中的空字符串

            import numpy as np
            
            df['new_col'].replace(r'^\s*$', np.nan, regex=True, inplace=True)
            

            完整代码:

            import pandas as pd
            import numpy as np
            
            df = pd.DataFrame({'foodstuff':['apple-martini', 'apple-pie', None, None, None], 'type':[None, None, 'strawberry-tart', 'dessert', None]})
            
            df['new_col'] = df['foodstuff'].fillna('') + df['type'].fillna('')
            
            df['new_col'].replace(r'^\s*$', np.nan, regex=True, inplace=True)
            
            df
            

            输出:

                foodstuff   type    new_col
            0   apple-martini   None    apple-martini
            1   apple-pie   None    apple-pie
            2   None    strawberry-tart strawberry-tart
            3   None    dessert dessert
            4   None    None    NaN
            

            【讨论】:

            • 一般解决方案还应为数字数据类型提供零替换值 (.fillna(default_str_or_val))
            猜你喜欢
            • 2020-03-30
            • 1970-01-01
            • 2018-04-23
            • 1970-01-01
            • 2023-01-30
            • 1970-01-01
            • 2021-09-28
            • 2021-06-21
            • 1970-01-01
            相关资源
            最近更新 更多