【问题标题】:How to replace all non-NaN entries of a dataframe with 1 and all NaN with 0如何用 1 替换数据帧的所有非 NaN 条目,用 0 替换所有 NaN
【发布时间】:2021-07-26 12:04:31
【问题描述】:

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

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

然后我使用 data_new=data.subtract(data) 将数据帧的所有值减去自身,这样我就可以将所有非空值设为 0。 但是由于数据框有多个字符串条目,因此发生了错误。

【问题讨论】:

标签: python pandas dataframe


【解决方案1】:

您可以获取df.notnull() 的返回值,即False,其中DataFrame 包含NaNTrue,否则将其转换为整数,给您0,其中DataFrame 为NaN1 否则:

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

如果您真的想写入原始 DataFrame,这将起作用:

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

【讨论】:

  • 对不起,请不要抄袭我的回答。我觉得你的版本和我的差不多,所以我觉得没必要。
  • 你注意到我在你面前发布了这个答案吗?
  • 是的,但不是notnull()。你的答案是~isnull()。而且它是平等的,所以我认为你的解决方案和我的一样好。
  • 你是对的,我们的两个答案以几乎相同的方式达到相同的效果。我试图通过删除不必要的双重反转来改进我的答案。
  • 是的,我理解你。但不幸的是,如果某些答案更好,我认为复制它是不好的。你可以投票 -;) [我在 SO 中只做了两次,因为我知道订购量很低:(
【解决方案2】:

使用notnull 将布尔值转换为int by astype

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

【讨论】:

  • 如果你对这个答案的反面感兴趣:(df.isnull()).astype('int')
【解决方案3】:

我进行了大量数据分析,并且有兴趣寻找新的/更快的执行操作的方法。我从来没有遇到过 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 秒的时间。谁是赢家一目了然。

【讨论】:

    【解决方案4】:

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

    例如如果 df['col1'] 是现有列

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

    其中 col2 是新列。如果 col2 有字符串条目,也应该可以工作。

    【讨论】:

      【解决方案5】:

      DataFrames 上有一个方法 .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
      

      【讨论】:

      • 这只是部分回答了问题,问题是关于替换 NaN 和非 NaN。
      【解决方案6】:

      在这里,我将给出一个建议,以获取特定列,如果该列中的行是 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)
      

      同样可以通过不定义列名称应用于整个数据框

      【讨论】:

      • 开头为0的值呢?
      • @B.Go 会将 NaN 值更改为 0 以在第二行检查 0。我尝试检查第二行,就像“NaN”一样,但这是一个错误。你不能,要像这样检查 NaN,你需要使用 Numpy。所以这对我来说是最简单的方法。
      【解决方案7】:

      对于 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
      

      【讨论】:

        【解决方案8】:

        试试这个:

        df.notnull().mul(1)
        

        【讨论】:

          【解决方案9】:

          使用:df.fillna(0)

          用 0 填充 NaN。

          【讨论】:

            【解决方案10】:

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

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

            旁注:如果您查看 pandas 文档,.where 会替换所有值,即False - 这很重要。这就是我们使用反转来创建掩码~dataframe.notna() 的原因,.where() 将通过该掩码替换值

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2022-07-06
              • 2021-03-08
              • 2021-07-16
              • 2018-08-28
              • 2019-11-24
              • 1970-01-01
              • 2021-08-17
              • 1970-01-01
              相关资源
              最近更新 更多