在进行Titanic幸存者预测的过程中,数据预处理涉及到空值填充。我的想法是以Pclass分组,为Age的空值填充随机值x~U(mean-σ,mean+σ)


一、warning

开始是参考其他文章的做法,但情况不一样,那篇文章并没有分组赋值,由于不涉及分组,所以对dataframe赋值时是一整列进行赋值的,而这是pandas官方建议的赋值方法之一

import pandas as pd
import numpy as np


train_data = pd.read_csv('data/train.csv')

for pclass in train_data.Pclass.unique():
    class_age = train_data['Age'][train_data.Pclass == pclass]
    age_null = class_age.isnull().sum()
    mean = class_age.mean()
    std = class_age.std()
    randage = np.random.randint(mean - std, mean + std, size=age_null)
    age_slice = class_age.copy()
    age_slice[np.isnan(age_slice)] = randage
    train_data['Age'][train_data.Pclass == pclass] = age_slice

在for循环的最后一行

train_data['Age'][train_data.Pclass == pclass] = age_slice

等号左边由于有[train_data.Pclass == pclass],因此是一个Dataframe的切片(slice),对一个切片赋值会有如下警告,当然这种赋值是可以完成的,但我想要使用官方推荐的方法来完成

SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame

二、

1.取值赋值

Dataframe取值赋值有多种方法,但我认为可以分为两类
第一类:使用方括号[]

# 取一列
df.B
df[B]
# 设置条件
df.B[df.A>4]
df.B[df.A>4][df.B.isnull()]

第二类:使用函数.loc()/.iloc()(本文不讨论两者区别)

# 使用索引
df.iloc[2,2]
# 使用索引名
df.loc['一','B'] 
# 取多行
df.loc[:,"年龄"]

2. .loc()

pandas官方的建议是使用.loc()来完成。
.loc()可以读取指定位置的值,也可以对指定位置进行赋值
.loc()的第一个参数(index)指定行,第二个参数(columns)指定列,而且使用:取多行/列时,是"前闭后闭",也就是:两边都能取到

但我希望的是为行添加多个条件
这是能办到的,如下

mask = (df.A==a)&(df.b>20)&(df.c.isnull())
df.loc[mask,'d']

注意各条件使用()括起来,如果条件简单,不使用mask也是可行的,如

df.d.loc[(df.d>20)&(df.d<=30)]

那么我的原代码,在for循环的最后三行改为以下代码即可

mask = (train_data.Pclass == pclass) & (train_data.Age.isnull())
train_data.loc[mask, 'Age'] = randage

参考:
1.最底下是解决方法(全英)
2.这个pdf就一页,可以试读全部
3.其他赋值方法
4.查找有空值的行
5.空值判断

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐