【发布时间】:2013-09-12 10:41:45
【问题描述】:
我有一个大部分填充实数的 pandas DataFrame,但其中也有一些 nan 值。
如何将nans 替换为它们所在列的平均值?
这个问题与这个问题非常相似:numpy array: replace nan values with average of columns,但不幸的是,那里给出的解决方案不适用于 pandas DataFrame。
【问题讨论】:
我有一个大部分填充实数的 pandas DataFrame,但其中也有一些 nan 值。
如何将nans 替换为它们所在列的平均值?
这个问题与这个问题非常相似:numpy array: replace nan values with average of columns,但不幸的是,那里给出的解决方案不适用于 pandas DataFrame。
【问题讨论】:
您可以简单地使用DataFrame.fillna 直接填写nan:
In [27]: df
Out[27]:
A B C
0 -0.166919 0.979728 -0.632955
1 -0.297953 -0.912674 -1.365463
2 -0.120211 -0.540679 -0.680481
3 NaN -2.027325 1.533582
4 NaN NaN 0.461821
5 -0.788073 NaN NaN
6 -0.916080 -0.612343 NaN
7 -0.887858 1.033826 NaN
8 1.948430 1.025011 -2.982224
9 0.019698 -0.795876 -0.046431
In [28]: df.mean()
Out[28]:
A -0.151121
B -0.231291
C -0.530307
dtype: float64
In [29]: df.fillna(df.mean())
Out[29]:
A B C
0 -0.166919 0.979728 -0.632955
1 -0.297953 -0.912674 -1.365463
2 -0.120211 -0.540679 -0.680481
3 -0.151121 -2.027325 1.533582
4 -0.151121 -0.231291 0.461821
5 -0.788073 -0.231291 -0.530307
6 -0.916080 -0.612343 -0.530307
7 -0.887858 1.033826 -0.530307
8 1.948430 1.025011 -2.982224
9 0.019698 -0.795876 -0.046431
fillna 的文档字符串说 value 应该是标量或字典,但是,它似乎也可以与 Series 一起使用。如果你想传递一个字典,你可以使用df.mean().to_dict()。
【讨论】:
df.fillna(df.mean()) 将返回新的数据帧,因此您必须写 df=df.fillna(df.mean()) 来保留它。
df=df.fillna(df.mean())代替df.fillna(df.mean(), inplace=True)
试试:
sub2['income'].fillna((sub2['income'].mean()), inplace=True)
【讨论】:
In [16]: df = DataFrame(np.random.randn(10,3))
In [17]: df.iloc[3:5,0] = np.nan
In [18]: df.iloc[4:6,1] = np.nan
In [19]: df.iloc[5:8,2] = np.nan
In [20]: df
Out[20]:
0 1 2
0 1.148272 0.227366 -2.368136
1 -0.820823 1.071471 -0.784713
2 0.157913 0.602857 0.665034
3 NaN -0.985188 -0.324136
4 NaN NaN 0.238512
5 0.769657 NaN NaN
6 0.141951 0.326064 NaN
7 -1.694475 -0.523440 NaN
8 0.352556 -0.551487 -1.639298
9 -2.067324 -0.492617 -1.675794
In [22]: df.mean()
Out[22]:
0 -0.251534
1 -0.040622
2 -0.841219
dtype: float64
应用每列的平均值并填充
In [23]: df.apply(lambda x: x.fillna(x.mean()),axis=0)
Out[23]:
0 1 2
0 1.148272 0.227366 -2.368136
1 -0.820823 1.071471 -0.784713
2 0.157913 0.602857 0.665034
3 -0.251534 -0.985188 -0.324136
4 -0.251534 -0.040622 0.238512
5 0.769657 -0.040622 -0.841219
6 0.141951 0.326064 -0.841219
7 -1.694475 -0.523440 -0.841219
8 0.352556 -0.551487 -1.639298
9 -2.067324 -0.492617 -1.675794
【讨论】:
虽然下面的代码完成了这项工作,但它的性能受到了很大的影响,因为您处理的 DataFrame 的记录数为 100k 或更多:
df.fillna(df.mean())
根据我的经验,应该仅在需要的地方替换 NaN 值(无论是平均值还是中位数),而不是在整个 DataFrame 中应用 fillna()。
我有一个包含 20 个变量的 DataFrame,其中只有 4 个需要 NaN 值处理(替换)。我尝试了上面的代码(代码 1),以及它的稍微修改的版本(代码 2),我有选择地运行它。即仅适用于具有 NaN 值的变量
#------------------------------------------------
#----(Code 1) Treatment on overall DataFrame-----
df.fillna(df.mean())
#------------------------------------------------
#----(Code 2) Selective Treatment----------------
for i in df.columns[df.isnull().any(axis=0)]: #---Applying Only on variables with NaN values
df[i].fillna(df[i].mean(),inplace=True)
#---df.isnull().any(axis=0) gives True/False flag (Boolean value series),
#---which when applied on df.columns[], helps identify variables with NaN values
以下是我观察到的性能,因为我不断增加 DataFrame 中的 # 条记录
数据帧约 10 万条记录
数据帧约 20 万条记录
拥有约 160 万条记录的 DataFrame
拥有约 1300 万条记录的 DataFrame
抱歉,回答很长!希望这会有所帮助!
【讨论】:
timed it以上所有方法,你的方法是最快的。谢谢大佬。
# To read data from csv file
Dataset = pd.read_csv('Data.csv')
X = Dataset.iloc[:, :-1].values
# To calculate mean use imputer class
from sklearn.impute import SimpleImputer
imputer = SimpleImputer(missing_values=np.nan, strategy='mean')
imputer = imputer.fit(X[:, 1:3])
X[:, 1:3] = imputer.transform(X[:, 1:3])
【讨论】:
如果您想用均值来估算缺失值,并且您想逐列进行,那么这只会用该列的平均值来估算。这可能更具可读性。
sub2['income'] = sub2['income'].fillna((sub2['income'].mean()))
【讨论】:
直接用df.fillna(df.mean())把所有的空值都填上均值
如果你想用该列的平均值填充空值,那么你可以使用这个
假设x=df['Item_Weight'] 这里Item_Weight 是列名
我们在这里赋值(用 x 的平均值填充 x 的空值到 x 中)
df['Item_Weight'] = df['Item_Weight'].fillna((df['Item_Weight'].mean()))
如果你想用一些字符串填充空值,那么使用
这里Outlet_size是列名
df.Outlet_Size = df.Outlet_Size.fillna('Missing')
【讨论】:
除上述之外的另一个选择是:
df = df.groupby(df.columns, axis = 1).transform(lambda x: x.fillna(x.mean()))
它不如以前的平均值响应优雅,但如果您希望用其他列函数替换空值,它可能会更短。
【讨论】:
Pandas:如何将 NaN (nan) 值替换为一列的平均值、中位数或其他统计数据
假设您的 DataFrame 是 df,并且您有一个名为 nr_items 的列。这是:df['nr_items']
如果您想替换 df['nr_items'] 列的NaN 值与列的平均值:
使用方法.fillna():
mean_value=df['nr_items'].mean()
df['nr_item_ave']=df['nr_items'].fillna(mean_value)
我创建了一个名为nr_item_ave 的新df 列来存储新列,其中NaN 值替换为列的mean 值。
使用mean 时应小心。如果您有异常值,更推荐使用median
【讨论】:
使用sklearn库预处理类
from sklearn.impute import SimpleImputer
missingvalues = SimpleImputer(missing_values = np.nan, strategy = 'mean', axis = 0)
missingvalues = missingvalues.fit(x[:,1:3])
x[:,1:3] = missingvalues.transform(x[:,1:3])
注意:在最近的版本中参数missing_values的值从NaN更改为np.nan
【讨论】:
我使用这种方法通过列的平均值来填充缺失值。
fill_mean = lambda col : col.fillna(col.mean())
df = df.apply(fill_mean, axis = 0)
【讨论】:
您还可以使用value_counts 来获取最常见的值。这适用于不同的数据类型。
df = df.apply(lambda x:x.fillna(x.value_counts().index[0]))
Here 是 value_counts api 引用。
【讨论】: