[英]Fillna in multiple columns in place in Python Pandas
我有一個混合類型的熊貓數據框,有些是字符串,有些是數字。 我想將字符串列中的 NAN 值替換為“。”,並將浮點列中的 NAN 值替換為 0。
考慮這個虛構的小例子:
df = pd.DataFrame({'Name':['Jack','Sue',pd.np.nan,'Bob','Alice','John'],
'A': [1, 2.1, pd.np.nan, 4.7, 5.6, 6.8],
'B': [.25, pd.np.nan, pd.np.nan, 4, 12.2, 14.4],
'City':['Seattle','SF','LA','OC',pd.np.nan,pd.np.nan]})
現在,我可以用 3 行來完成:
df['Name'].fillna('.',inplace=True)
df['City'].fillna('.',inplace=True)
df.fillna(0,inplace=True)
由於這是一個小數據框,因此 3 行可能就可以了。 在我的真實示例中(由於數據機密性原因,我無法在此分享),我有更多的字符串列和數字列。 所以我最終只為fillna寫了很多行。 有沒有一種簡潔的方法來做到這一點?
在尋找此問題的答案時遇到此頁面,但不喜歡現有答案。 我最終在DataFrame.fillna 文檔中找到了更好的東西,並認為我會為發生這種情況的其他人做出貢獻。
如果您有多個列,但只想替換其中一部分中的NaN
,則可以使用:
df.fillna({'Name':'.', 'City':'.'}, inplace=True)
這還允許您為每列指定不同的替換。 如果你想繼續填充所有剩余的NaN
值,你可以在最后拋出另一個fillna
:
df.fillna({'Name':'.', 'City':'.'}, inplace=True).fillna(0, inplace=True)
編輯(2021 年 4 月 22 日)
自原始帖子以來,功能(可能/顯然)發生了變化,您不能再鏈接 2 個inplace
fillna()
操作。 您仍然可以鏈接,但現在必須將該鏈分配給df
而不是就地修改,例如:
df = df.fillna({'Name':'.', 'City':'.'}).fillna(0)
您可以通過檢查dtype.kind
檢查dtype
是否為numeric
來apply
您的列:
res = df.apply(lambda x: x.fillna(0) if x.dtype.kind in 'biufc' else x.fillna('.'))
print(res)
A B City Name
0 1.0 0.25 Seattle Jack
1 2.1 0.00 SF Sue
2 0.0 0.00 LA .
3 4.7 4.00 OC Bob
4 5.6 12.20 . Alice
5 6.8 14.40 . John
您可以手動列出字符串列,也可以從df.dtypes
中收集它們。 獲得字符串/對象列的列表后,您可以一次在所有這些列上調用fillna
。
# str_cols = ['Name','City']
str_cols = df.columns[df.dtypes==object]
df[str_cols] = df[str_cols].fillna('.')
df = df.fillna(0)
定義一個函數:
def myfillna(series):
if series.dtype is pd.np.dtype(float):
return series.fillna(0)
elif series.dtype is pd.np.dtype(object):
return series.fillna('.')
else:
return series
如果您想以其他方式填充不同 dtype 的列,您可以添加其他 elif 語句。 現在將此函數應用於數據框的所有列
df = df.apply(myfillna)
這與“就地”相同
有一種更簡單的方法,可以在一行中完成:
df.fillna({'Name':0,'City':0},inplace=True)
這不是一個了不起的改進,但如果你將它乘以 100,只寫列名 + ':0' 比復制和粘貼所有內容 100 次要快得多。
如果您想用相同的值(“v”)替換列列表(“lst”)
def nan_to_zero(df, lst, v):
d = {x:v for x in lst}
df.fillna(d, inplace=True)
return df
如果您不想指定單獨的每列替換值,您可以這樣做:
df[['Name', 'City']].fillna('.',inplace=True)
如果你不喜歡就地(像我一樣)你可以這樣做:
columns = ['Name', 'City']
df[columns] = df[columns].fillna('.')
實現這一點的最簡潔易讀的方法是使用df.select_dtypes.columns
,尤其是對於許多列。 ( df.select_dtypes
, df.columns
)
df.select_dtypes
返回一個新的df
,其中僅包含與您需要的 dtype 匹配的列。
df.columns
返回df
中的列名列表。
完整代碼:
float_column_names = df.select_dtypes(float).columns
df[float_column_names] = df[float_column_names].fillna(0)
string_column_names = df.select_dtypes(object).columns
df[string_column_names] df[string_column_names].fillna('.')
很簡單的方法是: dt.replace(pd.np.nan, "NA")
。 如果您想要其他替換,您應該使用下一個: dt.replace("pattern", "replaced by (new pattern)")
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.