【问题标题】:Pandas fillna with a lookup table带有查找表的 Pandas fillna
【发布时间】:2015-05-31 08:23:10
【问题描述】:

在填充 NaN 时遇到一些问题。我想取一个带有几个 NaN 的数据框列,并用基于另一列的值从“查找表”派生的值填充它们。 (你可能会从泰坦尼克号数据集中认出我的数据)...

    Pclass   Age
0   1        33
1   3        24
2   1        23
3   2        NaN
4   1        Nan

我想用系列“pclass_lookup”中的值填充 NaN:

pclass_lookup
1        38.1
2        29.4
3        25.2

我尝试过使用以下索引进行 fillna:

df.Age.fillna(pclass_lookup[df.Pclass]), but it gives me an error of 
    ValueError: cannot reindex from a duplicate axis

lambdas 也是一种尝试:

df.Age.map(lambda x: x if x else pclass_lookup[df.Pclass]

但是,这似乎也不能正确填写。我完全错过了这里的船吗? '

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    首先你有一个第 4 行的 duff 值,实际上你有字符串 'Nan' 这与 'NaN' 不同,所以即使你的代码确实有效,这个值也永远不会被替换。

    所以你需要替换那个 duff 值,然后你可以调用 map 来查找 NaN 值:

    In [317]:
    
    df.Age.replace('Nan', np.NaN, inplace=True)
    df.loc[df['Age'].isnull(),'Age'] = df['Pclass'].map(df1.pclass_lookup)
    df
    Out[317]:
       Pclass   Age
    0       1    33
    1       3    24
    2       1    23
    3       2  29.4
    4       1  38.1
    

    时间安排

    对于 5000 行的 df:

    In [26]:
    
    %timeit df.loc[df['Age'].isnull(),'Age'] = df['Pclass'].map(df1.pclass_lookup)
    100 loops, best of 3: 2.41 ms per loop
    In [27]:
    
    %%timeit
    def remove_na(x):
        if pd.isnull(x['Age']):
            return df1[x['Pclass']]
        else:
            return x['Age']
    df['Age'] =df.apply(remove_na, axis=1)
    1 loops, best of 3: 278 ms per loop
    In [28]:
    
    %%timeit
    nulls = df.loc[df.Age.isnull(), 'Pclass']
    df.loc[df.Age.isnull(), 'Age'] = df1.loc[nulls].values
    100 loops, best of 3: 3.37 ms per loop
    

    所以你在这里看到 apply 因为与其他两种矢量化方法相比,它在逐行缩放方面的迭代效果很差,但map 仍然是最快的。

    【讨论】:

    • 所有三个答案都很完美。 vrajs5 的功能非常简单。这个答案虽然看起来很密集,但正是我想要做的。附言。对不起南错字
    • 你可能会发现这样调用 map 会是最快的方法
    【解决方案2】:

    基于@vrajs5 的响应:

    # Create dummy data
    df = pd.DataFrame()
    df['Pclass'] = [1,3,1,2,1]
    df['Age'] = [33,24,23,None, None]
    pclass_lookup = pd.Series([38.1,29.4,25.2], index = range(1,4))
    
    # Solution:
    nulls = df.loc[df.Age.isnull(), 'Pclass']
    df.loc[df.Age.isnull(), 'Age'] = pclass_lookup.loc[nulls].values
    
    >>> df
       Pclass   Age
    0       1  33.0
    1       3  24.0
    2       1  23.0
    3       2  29.4
    4       1  38.1
    

    【讨论】:

      【解决方案3】:

      以下内容应该适合您:

      df = pd.DataFrame()
      df['Pclass'] = [1,3,1,2,1]
      df['Age'] = [33,24,23,None, None]
      df
         Pclass  Age
      0       1   33
      1       3   24
      2       1   23
      3       2  NaN
      4       1  NaN
      
      pclass_lookup = pd.Series([38.1,29.4,25.2], index = range(1,4))
      pclass_lookup
      1    38.1
      2    29.4
      3    25.2
      dtype: float64
      
      def remove_na(x):
          if pd.isnull(x['Age']):
              return pclass_lookup[x['Pclass']]
          else:
              return x['Age']
      df['Age'] =df.apply(remove_na, axis=1)
      
         Pclass   Age
      0       1  33.0
      1       3  24.0
      2       1  23.0
      3       2  29.4
      4       1  38.1
      

      【讨论】:

        猜你喜欢
        • 2019-02-24
        • 1970-01-01
        • 1970-01-01
        • 2020-04-26
        • 2019-10-02
        • 1970-01-01
        • 2022-11-03
        • 1970-01-01
        • 2017-01-07
        相关资源
        最近更新 更多