Python 如何将数据帧的所有非NaN项替换为1,将所有NaN项替换为0

Python 如何将数据帧的所有非NaN项替换为1,将所有NaN项替换为0,python,pandas,dataframe,Python,Pandas,Dataframe,我有一个71列30597行的数据框。我想用1替换所有非nan项,用0替换nan值 最初,我尝试对数据帧的每个值进行for循环,这花费了太多的时间 然后我使用了data\u new=data.subtract(data),这意味着要将数据帧的所有值减去它本身,这样我就可以将所有非空值设为0。 但是,由于数据框有多个字符串条目,因此出现了一个错误。通过以下方式将布尔值强制转换为int: 样本: import pandas as pd import numpy as np df = pd.DataF

我有一个71列30597行的数据框。我想用1替换所有非nan项,用0替换nan值

最初,我尝试对数据帧的每个值进行for循环,这花费了太多的时间

然后我使用了data\u new=data.subtract(data),这意味着要将数据帧的所有值减去它本身,这样我就可以将所有非空值设为0。 但是,由于数据框有多个字符串条目,因此出现了一个错误。

通过以下方式将布尔值强制转换为
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

您可以获取
df.notnull()
的返回值,如果数据帧包含
NaN
True
,则返回值为
False
,否则将其转换为整数,如果数据帧为
NaN
1
,则返回值为
0

newdf = df.notnull().astype('int')
如果您确实想写入原始数据帧,这将起作用:

df.loc[~df.isnull()] = 1  # not nan
df.loc[df.isnull()] = 0   # nan
在数据帧上有一种方法可以满足您的需要。例如:

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


我建议写一个新专栏,而不仅仅是替换。如有必要,您始终可以删除上一列,但通过对另一列的操作填充某列的源总是很有帮助的

e、 g.如果df['col1']是现有列

df['col2'] = df['col1'].apply(lambda x: 1 if not pd.isnull(x) else np.nan)
其中col2是新列。如果col2有字符串条目,也应该工作。

使用:
df.fillna(0)


用0填充NaN。

我做了大量数据分析,并对寻找新的/更快的操作方法感兴趣。我从未遇到过耶斯雷尔的方法,所以我很好奇地将其与我通常的方法进行比较(即用索引替换)。注:这不是对OP问题的回答,而是对耶斯雷尔方法效率的说明。由于这不是一个答案,如果人们觉得这篇文章没有用(而且在被否决后被遗忘!),我会删除它。如果你认为我应该删除它,请留下评论

我创建了一个中等大小的数据帧,并使用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秒。很清楚谁是赢家。

这里我将给出一个建议,选择一个特定的列,如果该列中的行为NaN,则将其替换为0,或者该列中的值将其替换为1

下面这一行将您的列更改为0

df.YourColumnName.fillna(0,inplace=True)
现在,Not Nan部分的其余部分将由下面的代码替换为1

df["YourColumnName"]=df["YourColumnName"].apply(lambda x: 1 if x!=0 else 0)
通过不为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

通常有两个步骤-替换所有非NAN值,然后替换所有NAN值

  • dataframe.where(~dataframe.notna(),1)
    -此行将所有非nan值替换为1
  • dataframe.fillna(0)
    -此行将把所有NAN替换为0

  • 旁注:如果您查看pandas文档,
    。其中
    替换所有值,即
    False
    ——这一点很重要。这就是为什么我们使用反转来创建一个掩码
    ~dataframe.notna()
    ,通过它
    。where()
    将替换值可能重复的对不起,请不要复制我的答案。我认为你的版本和我的相同,所以我认为没有必要。你注意到我在你之前发布了这个答案吗?是的,但不是使用
    notnull()
    。您的答案是使用
    ~isnull()
    。它是相等的,所以我认为你的解决方案和我的一样好。你是对的,我们的答案以几乎相同的方式达到了相同的效果。我试图通过删除一个不必要的双反转来改进我的答案。是的,我理解你。但不幸的是,如果有更好的答案,我认为它是坏的复制它。你可以投票表决-;)[我在中只做了两次,因为我知道排序很低:(开始时0处的值如何?@B.Go这会将NaN值更改为0,以便在第二行检查0。我尝试像“NaN”一样检查第二行,但这是一个错误。你不能,要像这样检查NaN,你需要使用Numpy。因此,这对我来说是一个简单的方法。
    df[~df.isnull()] = 1  # not nan
    df[df.isnull()] = 0   # nan
    
    change_col = ['a', 'b']
    tmp = df[change_col]
    tmp[tmp.isnull()]='xxx'
    df[change_col]=tmp