如何将另一整列作为参数传递给pandas fillna()


94

我想使用fillna方法使用另一列中的值填充一列中的缺失值。

(我读过,遍历每一行是非常不好的做法,最好一口气做完所有事情,但是我不知道该怎么做fillna。)

之前的数据:

Day  Cat1  Cat2
1    cat   mouse
2    dog   elephant
3    cat   giraf
4    NaN   ant

之后的数据:

Day  Cat1  Cat2
1    cat   mouse
2    dog   elephant
3    cat   giraf
4    ant   ant

Answers:


172

您可以将此列提供给fillna(请参阅docs),它将使用匹配索引上的那些值来填充:

In [17]: df['Cat1'].fillna(df['Cat2'])
Out[17]:
0    cat
1    dog
2    cat
3    ant
Name: Cat1, dtype: object

7
真好!我不知道fillna需要一系列。
阿米·塔沃里

1
谢谢!我认为该系列必须是NA值数量的确切大小。
xav 2015年

它也适用于多列行的数据帧。fillna的功能非常有帮助。
Wertikal

19

你可以做

df.Cat1 = np.where(df.Cat1.isnull(), df.Cat2, df.Cat1)

RHS的整体结构使用菜谱中的三元模式pandas(在任何情况下都需要阅读)。这是的向量版本a? b: c


不是我用于此问题的解决方案,而是非常有趣的模式!谢谢!
xav 2015年

有没有一种方法可以用于多列?例如,如果此df有cat1,cat2,cat3,cat4,cat5,而cat5为空。如果cat1为空然后cat2,如果cat2为空然后cat3,有没有办法用cat1的值填充cat5?
user8322222 '19

@ user8322222我肯定迟到了,但是如果有人遇到这个问题,您可以嵌套np.where,就像在excel cell = np.where(cond,val_true,np.where(cond,val_true,val_false)中一样, )。
凯萨尔

您要提及的是,这只是重新定义了内置的熊猫pd.DataFrame.fillna()。而且我怀疑极端情况的行为可能会有所不同,例如对于来自不同数据帧的序列长度不匹配:dfA ['Cat1'],dfB ['Cat2']
smci

8

只需使用value参数代替method

In [20]: df
Out[20]:
  Cat1      Cat2  Day
0  cat     mouse    1
1  dog  elephant    2
2  cat     giraf    3
3  NaN       ant    4

In [21]: df.Cat1 = df.Cat1.fillna(value=df.Cat2)

In [22]: df
Out[22]:
  Cat1      Cat2  Day
0  cat     mouse    1
1  dog  elephant    2
2  cat     giraf    3
3  ant       ant    4

谢谢你的回答!使用价值而不是joris所描述的方法会发生什么变化?
xav 2015年

@xavvalue是第一个参数,因此joris实际上在做同样的事情。正如他所说,请参阅文档
chrisaycock

是的,文档字符串有点误导,如method第一个列出的那样。
joris

7

pandas.DataFrame.combine_first也可以。

注意:由于“结果索引列将是各个索引和列的并集”,因此应检查索引和列是否匹配。

import numpy as np
import pandas as pd
df = pd.DataFrame([["1","cat","mouse"],
    ["2","dog","elephant"],
    ["3","cat","giraf"],
    ["4",np.nan,"ant"]],columns=["Day","Cat1","Cat2"])

In: df["Cat1"].combine_first(df["Cat2"])
Out: 
0    cat
1    dog
2    cat
3    ant
Name: Cat1, dtype: object

与其他答案比较:

%timeit df["Cat1"].combine_first(df["Cat2"])
181 µs ± 11.3 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

%timeit df['Cat1'].fillna(df['Cat2'])
253 µs ± 10.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%timeit np.where(df.Cat1.isnull(), df.Cat2, df.Cat1)
88.1 µs ± 793 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

我没有在下面使用此方法:

def is_missing(Cat1,Cat2):    
    if np.isnan(Cat1):        
        return Cat2
    else:
        return Cat1

df['Cat1'] = df.apply(lambda x: is_missing(x['Cat1'],x['Cat2']),axis=1)

因为它将引发一个异常:

TypeError: ("ufunc 'isnan' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''", 'occurred at index 0')

这意味着np.isnan可以应用于本机dtype的NumPy数组(例如np.float64),但是在应用于对象数组时会引发TypeError 。

所以我修改了方法:

def is_missing(Cat1,Cat2):    
    if pd.isnull(Cat1):        
        return Cat2
    else:
        return Cat1

%timeit df.apply(lambda x: is_missing(x['Cat1'],x['Cat2']),axis=1)
701 µs ± 7.38 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

0

这是一种更通用的方法(fillna方法可能更好)

def is_missing(Cat1,Cat2):    
    if np.isnan(Cat1):        
        return Cat2
    else:
        return Cat1

df['Cat1'] = df.apply(lambda x: is_missing(x['Cat1'],x['Cat2']),axis=1)

0

我知道这是一个老问题,但是最近我需要做类似的事情。我能够使用以下内容:

df = pd.DataFrame([["1","cat","mouse"],
    ["2","dog","elephant"],
    ["3","cat","giraf"],
    ["4",np.nan,"ant"]],columns=["Day","Cat1","Cat2"])

print(df)

  Day Cat1      Cat2
0   1  cat     mouse
1   2  dog  elephant
2   3  cat     giraf
3   4  NaN       ant

df1 = df.bfill(axis=1).iloc[:, 1]
df1 = df1.to_frame()
print(df1)

产生:

  Cat1
0  cat
1  dog
2  cat
3  ant

希望这对某人有帮助!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.