(本文大部分摘自实验楼“使用Pandas进行数据探索”)
如果还未了解Pandas的基础知识,烦请关闭本文,另找资料学习一下Pandas的基础知识。
本文目的是大致了解一下初级的数据分析流程。
一、加载数据
import numpy as np
import pandas as pd
import warnings
# 使用警告过滤器忽略警告
warnings.filterwarnings('ignore')
df = pd.read_csv('https://labfile.oss.aliyuncs.com/courses/1283/telecom_churn.csv')
数据已经加载好了,每次加载完最好顺手用一下df.head()
。
二、数据查看
数据在加载好后,首先用一下df.head()
,然后看看df.shape
和df.columns
等,在数据可视化之前,需要简单了解一下数据大致内容。
相关属性
# 查看行列数
df.shape
# 查看列名
df.columns
相关方法
# 查看一下df的总体信息,注意数据数量,是否有缺失值和数据类型
df.info()
# 查看一下df的统计学信息
df.describe()
# 也可以只看object和bool数据类型的数据信息
df.describe(include=['object','bool'])
# value_counts() 方法可以查看类别(类型为 object )和布尔值(类型为 bool )特征。
# 看下离网率Churn的分布
df['Churn'].value_counts()
# 也可以加上normalize参数显示比例
df['Churn'].value_counts(normalize=True)
# 按顺序查看:sort_values()
# 根据每日消费额倒序查看
df.sort_values(by='Total day charge', ascending=False).head()
# 先按 Churn升序排列,再按Total day charge每日总话费降序排列
df.sort_values(by=['Churn', 'Total day charge'],
ascending=[True, False]).head()
# 索引
# 可以直接加列名
df['Churn']
# 布尔值索引,离网用户的均值多少
df[df['Churn'] == 1].mean()
# 离网用户在白天打电话的总时长的均值是多少?
df[df['Churn'] == 1]['Total day minutes'].mean()
# 未使用国际套餐(International plan == NO)的忠实用户(Churn == 0)所打的最长的国际长途是多久?
df[(df['Churn'] == 0) & (df['International plan'] == 'No')
]['Total intl minutes'].max()
# 还可以使用loc()与iloc(),分别是显示索引和隐式索引
df.loc[0:5, 'State':'Area code']
df.iloc[0:5, 0:3]
# df[:1] 和 df[-1:] 可以得到 DataFrame 的首行和末行。
df[:1]
df[-1:]
三、数据探索
3.1 apply()
# 通过apply()方法应用函数max至每一列,即输出每列的最大值。
df.apply(np.max)
# apply()方法也可以应用函数至每一行,指定axis=1即可。
df[df['State'].apply(lambda state: state[0] == 'W')].head()
3.2 map()
# map()方法可以通过一个{old_value:new_value}形式的字典替换某一列中的值
d = {'No': False, 'Yes': True}
df['International plan'] = df['International plan'].map(d)
df.head()
# 当然上面的代码用replace()也行
df = df.replace({'Voice mail plan': d})
df.head()
3.3 pd.groupby()
columns_to_show = ['Total day minutes', 'Total eve minutes',
'Total night minutes']
# 根据churn的数据分组
df.groupby(['Churn'])[columns_to_show].describe(percentiles=[])
# 或者使用agg()
df.groupby(['Churn'])[columns_to_show].agg([np.mean, np.std, np.min, np.max])
3.4 透视表,pd.pivot_table()
# 通过pivot_table()方法查看不同区号下白天、夜晚、深夜的电话量的均值
df.pivot_table(['Total day calls', 'Total eve calls', 'Total night calls'],
['Area code'], aggfunc='mean')
3.5 交叉表,pd.crosstab()
# 构建一个交叉表查看样本的Churn离网率和International plan国际套餐的分布情况
pd.crosstab(df['Churn'], df['International plan'])
# 还可以使用normalize参数
pd.crosstab(df['Churn'], df['Voice mail plan'], normalize=True)
3.6 插入数据,insert()
在数据标准化的时候经常插一列新数据
total_calls = df['Total day calls'] + df['Total eve calls'] + \
df['Total night calls'] + df['Total intl calls']
df.insert(loc=len(df.columns), column='Total calls', value=total_calls)
# 其实也可以直接加
df['Total charge'] = df['Total day charge'] + df['Total eve charge'] + \
df['Total night charge'] + df['Total intl charge']
3.7 删除数据,drop()
# 移除先前创捷的列
df.drop(['Total charge', 'Total calls'], axis=1, inplace=True)
# 删除行
df.drop([1, 2]).head()
四、通过数据可视化来探索数据
这里使用的是seaborn,默认比matplotlib漂亮。sns.countplot()
是计数直方图。
# 加载模块,配置绘图
import matplotlib.pyplot as plt
import seaborn as sns
# 如果在Jupyter Notebook上运行能直接看到结果
sns.countplot(x='International plan', hue='Churn', data=df)
# 上图表明,开通了国际套餐的用户的离网率要高很多
# 查看Customer service calls客服呼叫 变量与Chunrn离网率的相关性
sns.countplot(x='Customer service calls', hue='Churn', data=df)
# 上图表明,在客服呼叫 4 次之后,客户的离网率显著提升。
为了更好的突出 Customer service call 客服呼叫 和 Churn 离网率 的关系,可以给 DataFrame
添加一个二元属性 Many_service_calls,即客户呼叫超过 3 次(Customer service calls >
3)。看下它与离网率的相关性,并可视化结果。
df['Many_service_calls'] = (df['Customer service calls'] > 3).astype('int')
sns.countplot(x='Many_service_calls', hue='Churn', data=df)
现在我们可以创建另一张交叉表,将 Churn 离网率 与 International plan 国际套餐 及新创建的 Many_service_calls 多次客服呼叫 关联起来。
pd.crosstab(df['Many_service_calls'] & df['International plan'], df['Churn'])