Python 如何将数据帧的所有非NaN项替换为1,将所有NaN项替换为0
我有一个71列30597行的数据框。我想用1替换所有非nan项,用0替换nan值 最初,我尝试对数据帧的每个值进行for循环,这花费了太多的时间 然后我使用了data\u new=data.subtract(data),这意味着要将数据帧的所有值减去它本身,这样我就可以将所有非空值设为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
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值替换为1dataframe.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