【问题标题】:Conditionally filling blank values in Pandas dataframes有条件地填充 Pandas 数据框中的空白值
【发布时间】:2019-03-17 19:56:12
【问题描述】:

我有一个如下所示的数据场(有更多列已被删除):

    memberID    shipping_country    
    264991      
    264991       Canada
    100          USA    
    5000         
    5000         UK

我正在尝试用每个用户的发货国家/地区的现有值填充 空白 单元格:

    memberID    shipping_country    
    264991       Canada
    264991       Canada
    100          USA    
    5000         UK
    5000         UK

但是,我不确定在大规模数据集上执行此操作的最有效方法是什么。也许,使用矢量分组方法?

【问题讨论】:

    标签: python pandas dataframe pandas-groupby series


    【解决方案1】:

    你可以使用GroupBy + ffill / bfill:

    def filler(x):
        return x.ffill().bfill()
    
    res = df.groupby('memberID')['shipping_country'].apply(filler)
    

    自定义函数是必要的,因为没有将 Pandas 方法组合到 ffillbfill 顺序。

    这也适用于特定memberID 的所有值都是NaN 的情况;在这种情况下,它们将保持为NaN

    【讨论】:

      【解决方案2】:

      对于以下示例数据框(我在shipping_country 列中添加了一个仅包含''memberID 组):

         memberID shipping_country
      0    264991                 
      1    264991           Canada
      2       100              USA
      3      5000                 
      4      5000               UK
      5        54                 
      

      这应该对您有用,并且如果memberID 组在shipping_country 中只有空字符串值(''),则这些值将保留在输出df 中:

      df['shipping_country'] = df.replace('',np.nan).groupby('memberID')['shipping_country'].transform('first').fillna('')
      

      产量:

         memberID shipping_country
      0    264991           Canada
      1    264991           Canada
      2       100              USA
      3      5000               UK
      4      5000               UK
      5        54                 
      

      如果您想在输出df 中将空字符串'' 保留为NaN,则只需删除fillna(''),留下:

      df['shipping_country'] = df.replace('',np.nan).groupby('memberID')['shipping_country'].transform('first')
      

      【讨论】:

        【解决方案3】:

        您可以使用链式groupbys,一种使用前向填充,一种使用回填:

        # replace blank values with `NaN` first:
        df['shipping_country'].replace('',pd.np.nan,inplace=True)
        
        df.iloc[::-1].groupby('memberID').ffill().groupby('memberID').bfill()
        
           memberID shipping_country
        0    264991           Canada
        1    264991           Canada
        2       100              USA
        3      5000               UK
        4      5000               UK
        

        此方法还将允许由所有NaN 组成的组保持NaN

        >>> df
           memberID shipping_country
        0    264991                 
        1    264991           Canada
        2       100              USA
        3      5000                 
        4      5000               UK
        5         1                 
        6         1                 
        
        df['shipping_country'].replace('',pd.np.nan,inplace=True)
        
        df.iloc[::-1].groupby('memberID').ffill().groupby('memberID').bfill()
        
           memberID shipping_country
        0    264991           Canada
        1    264991           Canada
        2       100              USA
        3      5000               UK
        4      5000               UK
        5         1              NaN
        6         1              NaN
        

        【讨论】:

        • 第二种方法 (ffill) 在此解决方案中是否按组工作?
        • 是的,你可以试试 OP 的测试数据,它不会溢出memberID 行:)
        • 感谢您的回答。如果一个组中的所有值都是 NaN,那么发货国家也将被标记为 NaN。
        • @sacul,如果您的空行位于顶部(对于 264991)怎么办?试试吧,在那种情况下,我看到bfill 被应用于系列(不是按组)。
        • 我认为这行不通。假设您反转了最后一个示例(df = df.iloc[::-1])。 bfill 将使 memberID=1 成为 UK,因为 bfill 不知道它应该只对组起作用。
        猜你喜欢
        • 2020-08-11
        • 1970-01-01
        • 2017-05-22
        • 2019-12-13
        • 2013-02-12
        • 1970-01-01
        • 2021-12-03
        • 2019-09-09
        • 2021-06-04
        相关资源
        最近更新 更多