pandas强化练习(美国交警开放的数据)
这篇文章写得更好:http://wittyfans.com/coding/%E5%88%A9%E7%94%A8Pandas%E5%88%86%E6%9E%90%E7%BE%8E%E5%9B%BD%E4%BA%A4%E8%AD%A6%E5%BC%80%E6%94%BE%E7%9A%84%E6%90%9C%E6%9F%A5%E6%95%B0%E6%8D%AE.html
import pandas as pd
import matplotlib.pyplot as plt
#需要声明才能在notebook中画图
%matplotlib inline
#下载的罗曼的警务数据,这里以ri代表罗德曼岛警务数据
ri=pd.read_csv('police.csv')
ri.head()
Out[2]:
In [3]:
ri.shape
Out[3]:
In [4]:
ri.isnull().sum()
Out[4]:
移除某列
In [5]:
ri.head()
Out[5]:
In [6]:
#写法等同于ri.drop('county_name', axis=1 , inplace=True)
#删除空值的
ri.drop('county_name', axis='columns', inplace=True)
In [7]:
ri.shape
Out[7]:
In [8]:
ri.columns
Out[8]:
In [9]:
#删除有空值的行
ri.dropna(axis='columns',how='all').shape
Out[9]:
pandas过滤功能
保留布尔值为真的数据,这里我们保留violaton值为真的数据
In [10]:
ri[ri.violation=='Speeding'].head()
Out[10]:
values_counts
In [11]:
## 超速违规的驾驶员男女各多少人
print(ri[ri.violation=='Speeding'].driver_gender.value_counts()
)
In [12]:
# 超速男女各占多少比例 normalize归一化处理
print(ri[ri.violation=='Speeding'].driver_gender.value_counts(normalize=True))
In [13]:
ri.loc[ri.violation=='Speeding','driver_gender'].value_counts(normalize=True)
Out[13]:
In [14]:
#男性驾驶员中,各种交通违规的比例
ri[ri.driver_gender == 'M'].violation.value_counts(normalize=True)
Out[14]:
In [15]:
#女性驾驶员中各种交通违规的比例
ri[ri.driver_gender=='F'].violation.value_counts(normalize=True)
Out[15]:
groupby方法
查看不同driver_gender,violation的各种值的占比
In [16]:
#对比以上两种数据
ri.groupby('driver_gender').violation.value_counts(normalize=True)
Out[16]:
mean方法
mean可以默认计算占比
In [17]:
#True为执行搜查,False为未执行搜查
print(ri.search_conducted.value_counts(normalize=True))
In [18]:
#这例men可以计算出True的咋还占比
print(ri.search_conducted.mean())
男女分组看他们的搜索值
In [19]:
ri.groupby('driver_gender').search_conducted.mean()
Out[19]:
男的搜查比例比女的高
再看一下如果是多重分组,男女搜查的比例
In [20]:
ri.groupby(['violation','driver_gender']).search_conducted.mean()
Out[20]:
In [21]:
ri.isnull().sum()
Out[21]:
In [22]:
#是否search_conducted为false的时候,search_type都丢失了
ri.search_conducted.value_counts()
Out[22]:
是不是数值和上面的search_type丢失的值相同啊
再次验证一下
In [23]:
ri[ri.search_conducted==False].search_type.value_counts()
Out[23]:
In [24]:
#value_counts()这个方法时候默认忽略丢失值(空值)
ri[ri.search_conducted==False].search_type.value_counts(dropna=False)
Out[24]:
In [25]:
#当searcch_conducted的值为True,search_type从来不丢失
ri[ri.search_conducted==True].search_type.value_counts(dropna=False)
Out[25]:
In [26]:
ri[ri.search_conducted==True].search_type.isnull().sum()
Out[26]:
查看搜索类型
In [27]:
ri.search_type.value_counts(dropna=False)
Out[27]:
In [28]:
ri['frisk']=ri.search_type=='Protective Frisk'
In [29]:
ri.frisk.dtype
Out[29]:
In [30]:
ri.frisk.sum()
Out[30]:
In [31]:
ri.frisk.mean()
Out[31]:
In [32]:
ri.frisk.value_counts()
Out[32]:
In [33]:
161/(91580+161)
Out[33]:
字符操作
In [35]:
#上面的操作是把ri.search_type=='Protective Frisk'的值付给日['firsk']这一列
#现在是字符串的包含操作
ri['frisk']=ri.search_type.str.contains('Protective Frisk')
In [36]:
ri.frisk.sum()
Out[36]:
In [37]:
ri.frisk.mean()
Out[37]:
In [38]:
#用mean()计算符合条件和不符合条件的占比
ri.frisk.value_counts()
Out[38]:
In [41]:
#再看一下他们的计算是否和men()的结构一样
274/(2922+274)
Out[41]:
上面的这一部分是计算字符串匹配操作
用正确的关键字去计算比例
pandas计算式忽略缺失值的
In [42]:
#那一年的数据最少
ri.stop_date.str.slice(0,4).value_counts()
Out[42]:
In [43]:
#将ri.stop_date转化为datetime的格式的dataframe,存到stop_datetime新列中
ri['stop_datetime'] = pd.to_datetime(ri.stop_date)
#注意这里有dt方法,类似于上面的str方法
#dt后可以使用year、month等方法
ri.stop_datetime.dt.year.value_counts()
Out[43]:
In [44]:
ri.stop_datetime.dt.month.value_counts()
Out[44]:
In [46]:
#关于毒驾
ri.drugs_related_stop.dtype
Out[46]:
In [48]:
#基础比例
ri.drugs_related_stop.mean()
Out[48]:
In [55]:
#不能使用小时分组,除非你创建了小时这一列
#取出小时列,转换成时间格式,再转化才成小时分组
ri['stop_time_datetime']=pd.to_datetime(ri.stop_time)
ri.groupby(ri.stop_time_datetime.dt.hour).drugs_related_stop.mean()
Out[55]:
In [58]:
#按小时的时毒驾频率分布图
ri.groupby(ri.stop_time_datetime.dt.hour).drugs_related_stop.mean().plot()
Out[58]:
In [63]:
#按小时的,毒驾数量分布图
ri.stop_time_datetime.dt.hour.value_counts().plot()
Out[63]:
In [65]:
#按小时分组,毒驾数量排序分布图
ri.stop_time_datetime.dt.hour.value_counts().sort_index().plot()
Out[65]:
In [66]:
ri.groupby(ri.stop_time_datetime.dt.hour).stop_date.count().plot()
Out[66]:
In [68]:
#把无用的数据标记为丢失值
ri.stop_duration.value_counts()
Out[68]:
In [73]:
ri[(ri.stop_duration=='1')|(ri.stop_duration=='2')].stop_duration='NaN'
In [74]:
ri.stop_duration.value_counts()
Out[74]:
In [75]:
ri.loc[(ri.stop_duration=='1')|(ri.stop_duration=='2'),'stop_duration']='NaN'
In [76]:
ri.stop_duration.value_counts(dropna=False)
Out[76]:
In [77]:
#用执行的nan类型替换NaN
import numpy as np
ri.loc[ri.stop_duration == 'NaN', 'stop_duration'] = np.nan
In [79]:
ri.stop_duration.value_counts(dropna=False)
Out[79]:
In [80]:
ri.stop_duration.replace(['1', '2'], value=np.nan, inplace=True)
In [118]:
# stop_duration中的各种比例
#Series的map方法可以接受一个函数或含有映射关系的字典型对象。
#对某一个列进行批操作,本文中是批量替换
mapping={'0-15 Min':8,'16-30 Min':23,'30+ Min':45}
#记得这不是原地操作原始数据,需要新建一列存储map后的结果
ri['stop_minutes'] = ri.stop_duration.map(mapping)
In [119]:
#为各种粘皮匹配值
ri.stop_minutes.value_counts()
Out[119]:
In [120]:
ri.groupby('violation_raw').stop_minutes.mean()
Out[120]:
In [143]:
# 使用某种方法如mean、count对某类数据进行操作。
# 过去agg只能groupby之后的数据进行操作,现在还可以对dataframe类、series类进行操作。
ri.groupby('violation_raw').stop_minutes.agg(['mean','count'])
Out[143]:
plot 默认是折线方法
In [165]:
ri.groupby('violation_raw').stop_minutes.mean().plot()
Out[165]:
In [167]:
#换成bartu
ri.groupby('violation_raw').stop_minutes.mean().plot(kind='bar')
Out[167]:
In [168]:
ri.groupby('violation_raw').stop_minutes.mean().plot(kind='barh')
Out[168]:
In [147]:
ri.groupby('violation').driver_age.describe()
Out[147]:
In [148]:
ri.driver_age.plot(kind='hist')
Out[148]:
In [149]:
ri.driver_age.value_counts().sort_index().plot()
Out[149]:
In [150]:
ri.hist('driver_age', by='violation')
Out[150]:
In [151]:
ri.hist('driver_age',by='violation',sharex=True)
Out[151]:
In [152]:
ri.hist('driver_age',by='violation',sharex=True,sharey=True)
Out[152]:
In [153]:
ri.head()
Out[153]:
In [154]:
ri.tail()
Out[154]:
In [155]:
ri['new_age']=ri.stop_datetime.dt.year-ri.driver_age_raw
In [156]:
ri[['driver_age','new_age']].hist()
Out[156]:
In [157]:
ri[['driver_age','new_age']].describe()
Out[157]:
In [158]:
ri[(ri.new_age<15)|(ri.new_age>99)].shape
Out[158]:
In [159]:
ri.driver_age_raw.isnull().sum()
Out[159]:
In [160]:
ri.driver_age.isnull().sum()
Out[160]:
In [161]:
5621-5327
Out[161]:
In [162]:
ri[(ri.driver_age_raw.notnull())&(ri.driver_age.isnull())].head()
Out[162]:
In [163]:
ri.loc[(ri.new_age<15)|(ri.new_age>99),'new_age']=np.nan
In [164]:
ri.new_age.equals(ri.driver_age)
Out[164]: