本文将以kaggle比赛:Titanic: Machine Learning from Disaster为例,简要总结一下在数据分析关于numpy、pandas和matplotlib一些常用的函数操作
1. 文件读取
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
train=pd.read_csv('train.csv')
test=pd.read_csv('test.csv')
concat函数先将训练集与测试集合并
titanic=pd.concat([train, test], sort=False)
2. 数据分析
- 初步观察:观察特征个数,特征类型,缺失值情况
train.head()
train.info()
train.describe()
- 数据分析(绘图)
在画图方面,我们有多种选择: - 在一张画布画多张图:
fig = plt.figure()
plt.subplot2grid((2,3),(0,0)) # 在一张大图里分列几个小图,subplot2grid()函数可以使图超过边界
train.Survived.value_counts().plot.bar()
plt.title('获救情况') # 标题
plt.ylabel('人数') # y坐标
plt.subplot2grid((2,3),(0,1))
train.Pclass.value_counts().plot.bar()
plt.ylabel(u"人数")
plt.title(u"乘客等级分布")
plt.subplot2grid((2,3),(0,2))
plt.scatter(train.Survived, train.Age)#绘制散点图
plt.ylabel(u"年龄")
plt.title(u"按年龄看获救分布")
plt.subplot2grid((2,3),(1,0))
train.Age[data_train.Pclass == 1].plot.kde()#绘制密度图
train.Age[data_train.Pclass == 2].plot.kde()
train.Age[data_train.Pclass == 3].plot.kde()
plt.xlabel(u"年龄")
plt.ylabel(u"密度")
plt.title(u"各等级的乘客年龄分布")
plt.legend(('头等舱', '2等舱','3等舱'),loc='best') # 图例
fig=plt.figure()
ax2=fig.add_subplot(231,sharey=ax1)# 共享y轴
fig,axes=plt.subplot(2,3)
axes[i,j].plot(2,3,1)
- 直接画图:
train.Survived.value_counts().bar.plot()
- 当我们需要对两种特征按统计数量画图时可以结合交叉表(crosstab)如:性别与存活的关系:
pd.crosstab(train.Sex,train.Survived).plot.bar(stacked=True)#前面的数据为行,最后一个为列
多种整合:
Survived_cabin = titanic.Survived[pd.notnull(titanic.Cabin)].value_counts()# 分别提取有无船舱
Survived_nocabin = titanic.Survived[pd.isnull(titanic.Cabin)].value_counts()
df=pd.DataFrame({u'1':Survived_cabin, u'0':Survived_nocabin}).transpose()# 转化成dataframe类型
df.plot(kind='bar', stacked=True)
- 我们也可以观测在获救这一特殊条件下的男女比例分布:
train.Sex[train.Survived == 1].value_counts().plot.bar()
#外层为特征分布,内层为限制条件
3.数据清洗:
缺失较多使用随机森林预测补充:
from sklearn.ensemble import RandomForestRegressor
age_df = titanic[['Age', 'Pclass','Sex','Title']]
known_age = age_df[age_df.Age.notnull()].values
unknown_age = age_df[age_df.Age.isnull()].values
y = known_age[:, 0]
X = known_age[:, 1:]
rfr = RandomForestRegressor(random_state=0, n_estimators=100, n_jobs=-1)
rfr.fit(X, y)
predictedAges = rfr.predict(unknown_age[:, 1::])
all_data.loc[ (all_data.Age.isnull()), 'Age' ] = predictedAges #填充列中的指定项
缺失较少先观察缺失值的其他属性,然后直接填充:
显示含有缺失值所在的行:
titanic[titanic['Embarked'].isnull()]
缺失Embarked信息的乘客的Pclass均为1,且Fare均为80
使用groupby函数分组观察
[input]:
gp=titanic['Fare'].groupby([titanic['Pclass'],titanic['Embarked']])#第一个需要统计的值,参数为索引项
gp.median()
[Output]:
Pclass Embarked
1 C 78.2667
Q 90.0000
S 52.0000
2 C 15.3146
Q 12.3500
S 15.3750
3 C 7.8958
Q 7.7500
S 8.0500
Name: Fare, dtype: float64
因为Embarked为C且Pclass为1的乘客的Fare中位数为80,所以缺失值填充为C
titanic.Emarked = titanic.Embarked.fillna('C')
4.特征工程:
- 从姓名特征中提取称呼作为新特征:主要使用apply()函数和lambda函数
titanic['Title'] = titanic.Name.apply(lambda name: name.split(',')[1].split('.')[0].strip())
- 获取船舱号的首字母:
titanic['Cabin'] = titanic.Cabin.apply(lambda cabin: cabin[0])
- 将两个特征合并为一个新的特征,并删除原特征
titanic['FamilySize'] = titanic.Parch + titanic.SibSp + 1
titanic=titanic.drop(['SibSp','Parch'],axis=1)
- 使用get_dummies()特征因子化:
dummies_Cabin = pd.get_dummies(titanic['Cabin'], prefix= 'Cabin')
dummies_Embarked = pd.get_dummies(titanic['Embarked'], prefix= 'Embarked')
dummies_Sex = pd.get_dummies(titanic['Sex'], prefix= 'Sex')
dummies_Title = pd.get_dummies(titanic['Title'], prefix= 'Title')
titanic = pd.concat([titanic, dummies_Cabin, dummies_Embarked, dummies_Sex, dummies_Pclass], axis=1) # 列拼接
titanic.drop([ 'Sex', 'Title', 'Cabin', 'Embarked'], axis=1, inplace=True) #去除原有的
- 选取特征,使用values转换为ndarry数组,划分训练集和测试集
train=titanic[titanic['Survived'].notnull()]
test=all_data[titanic['Survived'].isnull()].drop('Survived',axis=1)
X = train.values[:,'Pclass':]
y = train.values[:,'Survived']
- 使用cut函数进行离散化:
titanic.Age=pd.cut(titanic.Age,8,labels=False)#分成8份
- 修改Title指定值的值:
- replace函数:
titanic.Title=titanic.Title.replace(['Capt', 'Col', 'Major', 'Dr', 'Rev'], 'Officer')
titanic.Title=titanic.Title.replace({'Capt':'Officer'})# 也可以使用字典
- loc函数:(不过我还不知道怎么替换所有值)
titanic.loc[titanic['Title'] =='Dona'] = 'Royalty'# df.loc[df.A>2]=0
#补充一个基于某一列修改另一列值
df.loc[df.A > 2, 'B'] = np.nan