簡體   English   中英

如何用 1 替換數據幀的所有非 NaN 條目,用 0 替換所有 NaN

[英]How to replace all non-NaN entries of a dataframe with 1 and all NaN with 0

我有一個包含 71 列和 30597 行的數據框。 我想用 1 替換所有非 nan 條目,用 0 替換 nan 值。

最初,我嘗試對數據幀的每個值進行 for 循環,這花費了太多時間。

然后我使用了data_new=data.subtract(data)這意味着將數據幀的所有值減去自身,以便我可以將所有非空值設為 0。但是由於數據幀有多個字符串條目而發生錯誤。

您可以獲取df.notnull()的返回值,當 DataFrame 包含NaNFalse ,否則為True並將其轉換為整數,在 DataFrame 為NaN0 ,否則為1

newdf = df.notnull().astype('int')

如果您真的想寫入原始數據幀,這將起作用:

df.loc[~df.isnull()] = 1  # not nan
df.loc[df.isnull()] = 0   # nan

使用notnull通過astype將 boolean 轉換為int

print ((df.notnull()).astype('int'))

樣本:

import pandas as pd
import numpy as np

df = pd.DataFrame({'a': [np.nan, 4, np.nan], 'b': [1,np.nan,3]})
print (df)
     a    b
0  NaN  1.0
1  4.0  NaN
2  NaN  3.0

print (df.notnull())
       a      b
0  False   True
1   True  False
2  False   True

print ((df.notnull()).astype('int'))
   a  b
0  0  1
1  1  0
2  0  1

.fillna()上有一個方法.fillna()可以滿足您的需求。 例如:

df = df.fillna(0)  # Replace all NaN values with zero, returning the modified DataFrame

要么

df.fillna(0, inplace=True)   # Replace all NaN values with zero, updating the DataFrame directly

我建議制作一個新專欄,而不是僅僅更換。 如有必要,您始終可以刪除前一列,但通過對另一列的操作填充列的源總是有幫助的。

例如,如果 df['col1'] 是現有列

df['col2'] = df['col1'].apply(lambda x: 1 if not pd.isnull(x) else np.nan)

其中 col2 是新列。 如果 col2 有字符串條目,也應該工作。

我進行了大量數據分析,並且有興趣尋找新的/更快的執行操作方法。 我從未遇到過 jezrael 的方法,所以我很好奇將它與我常用的方法(即通過索引替換)進行比較。 注意:這不是對 OP 問題的回答,而是對 jezrael 方法效率的說明。 由於這不是一個答案,如果人們認為它沒有用(並且在被低估之后被遺忘!),我將刪除這篇文章。 如果您認為我應該刪除它,請發表評論。

我創建了一個中等大小的數據框,並使用 df.notnull().astype(int) 方法和簡單的索引(我通常會這樣做)進行了多次替換。 事實證明,后者慢了大約五倍。 對於任何進行大規模更換的人來說,僅供參考。

from __future__ import division, print_function

import numpy as np
import pandas as pd
import datetime as dt


# create dataframe with randomly place NaN's
data = np.ones( (1e2,1e2) )
data.ravel()[np.random.choice(data.size,data.size/10,replace=False)] = np.nan

df = pd.DataFrame(data=data)

trials = np.arange(100)


d1 = dt.datetime.now()

for r in trials:
    new_df = df.notnull().astype(int)

print( (dt.datetime.now()-d1).total_seconds()/trials.size )


# create a dummy copy of df.  I use a dummy copy here to prevent biasing the 
# time trial with dataframe copies/creations within the upcoming loop
df_dummy = df.copy()

d1 = dt.datetime.now()

for r in trials:
    df_dummy[df.isnull()] = 0
    df_dummy[df.isnull()==False] = 1

print( (dt.datetime.now()-d1).total_seconds()/trials.size )

這分別產生 0.142 秒和 0.685 秒的時間。 誰是贏家,一目了然。

對於 fmarc 的回答:

df.loc[~df.isnull()] = 1  # not nan
df.loc[df.isnull()] = 0   # nan

上面的代碼對我不起作用,下面的代碼有效。

df[~df.isnull()] = 1  # not nan
df[df.isnull()] = 0   # nan

與熊貓 0.25.3

如果您只想更改特定列中的值,您可能需要創建一個臨時數據框並將其分配給原始數據框的列:

change_col = ['a', 'b']
tmp = df[change_col]
tmp[tmp.isnull()]='xxx'
df[change_col]=tmp

使用: df.fillna(0)

用 0 填充 NaN。

在這里,我將建議采用特定列,如果該列中的行是 NaN,則將其替換為 0 或該列中有值將其替換為 1

下面這行會將您的列更改為 0

df.YourColumnName.fillna(0,inplace=True)

現在非南部分的其余部分將被以下代碼替換為 1

df["YourColumnName"]=df["YourColumnName"].apply(lambda x: 1 if x!=0 else 0)

同樣可以通過不定義列名稱應用於總數據框

通常有兩個步驟 - 替換所有非 NAN 值,然后替換所有 NAN 值。

  1. dataframe.where(~dataframe.notna(), 1) - 此行將所有非 nan 值替換為 1。
  2. dataframe.fillna(0) - 此行將所有 NAN 替換為 0

旁注:如果您查看 pandas 文檔, .where替換所有值為False值 - 這很重要。 這就是為什么我們使用反轉來創建掩碼~dataframe.notna() ,其中.where()將替換值

試試這個:

df.notnull().mul(1)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM