Python Pandas数据框填充NaN值

6

我正在尝试使用来自标准正态分布的值填充数据框中的NaN值。以下是我的代码:

 sqlStatement = "select * from sn.clustering_normalized_dataset"
 df = psql.frame_query(sqlStatement, cnx)
 data=df.pivot("user","phrase","tfw")
 dfrand = pd.DataFrame(data=np.random.randn(data.shape[0],data.shape[1]))
 data[np.isnan(data)] = dfrand[np.isnan(data)]

对于数据框"data"进行透视后,它看起来像这样:

phrase      aaron  abbas  abdul       abe  able  abroad       abu     abuse  \
user                                                                          
14233664      NaN    NaN    NaN       NaN   NaN     NaN       NaN       NaN   
52602716      NaN    NaN    NaN       NaN   NaN     NaN       NaN       NaN   
123456789     NaN    NaN    NaN       NaN   NaN     NaN       NaN       NaN   
500158258     NaN    NaN    NaN       NaN   NaN     NaN       NaN       NaN   
517187571     0.4    NaN    NaN  0.142857     1     0.4  0.181818       NaN  

然而,我需要将每个NaN值替换为一个新的随机值。因此,我创建了一个仅包含随机值(dfrand)的新df,并尝试通过与NaN索引对应的dfrand值来交换缺失的数字(Nan)。遗憾的是,它不起作用 - 尽管表达式

 np.isnan(data)

返回一个由True和False值组成的数据框,该表达式

  dfrand[np.isnan(data)]

返回仅为NaN值,以使整个技巧无效。有什么问题吗?

2个回答

5

三千列并不算很多。你有多少行呢?你可以制作一个相同大小的随机数据框,并进行逻辑替换(你的数据框的大小将决定这是否可行)。

如果你知道你的数据框的大小:

import pandas as pd
import numpy as np

# create random dummy dataframe
dfrand = pd.DataFrame(data=np.random.randn(rows,cols))

# import "real" dataframe
data = pd.read_csv(etc.) # or however you choose to read it in

# replace nans
data[np.isnan(data)] = dfrand[np.isnan(data)]

如果您不知道数据框的大小,只需将其打乱即可。

import pandas as pd
import numpy as np



# import "real" dataframe
data = pd.read_csv(etc.) # or however you choose to read it in

# create random dummy dataframe
dfrand = pd.DataFrame(data=np.random.randn(data.shape[0],data.shape[1]))

# replace nans
data[np.isnan(data)] = dfrand[np.isnan(data)]

编辑 根据“用户”最后的评论: “dfrand [np.isnan(data)]仅返回NaN。”

没错!这正是您想要的。我的解决方案中有:data [np.isnan(data)] = dfrand [np.isnan(data)]。换句话说,这意味着:从dfrand中获取与“data”中的NaN位置相对应的随机生成值,并在“data”中将其插入到“data”为NaN的位置。以下是一个示例:

a = pd.DataFrame(data=np.random.randint(0,100,(10,3)))
a[0][5] = np.nan

In [32]: a
Out[33]: 
    0   1   2
0   2  26  28
1  14  79  82
2  89  32  59
3  65  47  31
4  29  59  15
5 NaN  58  90
6  15  66  60
7  10  19  96
8  90  26  92
9   0  19  23

# define randomly-generated dataframe, much like what you are doing, and replace NaN's
b = pd.DataFrame(data=np.random.randint(0,100,(10,3)))

In [39]: b
Out[39]: 
    0   1   2
0  92  21  55
1  65  53  89
2  54  98  97
3  48  87  79
4  98  38  62
5  46  16  30
6  95  39  70
7  90  59   9
8  14  85  37
9  48  29  46


a[np.isnan(a)] = b[np.isnan(a)]

In [38]: a
Out[38]: 
    0   1   2
0   2  26  28
1  14  79  82
2  89  32  59
3  65  47  31
4  29  59  15
5  46  58  90
6  15  66  60
7  10  19  96
8  90  26  92
9   0  19  23

如您所见,在中,所有 NaN 值都已用基于 nan-value 索引的随机生成值替换。


表达式np.isnan(data)在整个数据框中返回FALSE。虽然我确定有许多“NaN”值。有什么想法吗? - user4045430
你确定你有“真正的”nan值(即浮点数),还是只有字符串? - tnknepp
也许是我太蠢了。根据你如何读取数据框,你可能有字符串或浮点数/整数。如果你知道第一列中有NaN,那么你可以直接使用data.dtypes[data.columns[0]]。如果你得到的是dtype('float64'),那么你就知道你有一个“真正”的NaN,而不仅仅是字符串。话虽如此,你可能已经正确加载了它,而我只是太蠢了。"True in np.isnan(data)"返回True还是False? - tnknepp
更正:np.isnan(data)返回一些True值和一些False值。然而,dfrand[np.isnan(data)]仅返回NaN。我错过了什么吗?顺便说一句-dfrand完全按预期生成并包含随机数字。 - user4045430

0

假设您正在处理一个系列,您可以尝试类似于这样的东西:

ser = data['column_with_nulls_to_replace']
index = ser[ser.isnull()].index
df = pd.DataFrame(np.random.randn(len(index)), index=index, columns=['column_with_nulls_to_replace'])
ser.update(df)

如果我需要扫描所有列,我该怎么办?我应该将什么作为第一和第三个语句的参数传递? - user4045430
只需迭代。for c in data.columns: ... - acushner
1
我有超过3000列。也许有更快的方法? - user4045430
试一下,需要多长时间? - acushner

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接