一、概述
前面我们学习了pandas一些基本的知识,这一篇文章我们来学习pandas的数据处理,一些数学运算、排序、合并、apply数据预处理、去重、时间序列操作、分组,聚合、透视表等知识。
二、简单计算
首先我们先导入需要的模块:
import numpy as np
import pandas as pd
from pandas import Series, DataFrame
实例:
#Series 计算 可以计算加减乘,这里以加法为例
s1 = Series([1,2,3], index=['B','C','D'])
s2 = Series([4,5,6,7], index=['B','C','D','E'])
# 没有的数据为nan,对应的index相加
print(s1 + s2)
# DataFrame计算,可加减乘,以加法为例
df1 = DataFrame(np.arange(4).reshape(2,2), index=['A','B'], columns=['BJ','GZ'])
df2 = DataFrame(np.arange(9).reshape(3,3), index=['A','B','C'], columns=['BJ', 'GZ', 'SH'])
print(df1 + df2)#没有数据的NaN,对应的index做运算
结果:
-
DataFrame相关函数
DataFrame常用函数:sum()
、max()
、min()
、describe()
等
实例:
df3 = DataFrame([[1,2,3],[4,5,np.nan],[7,8,9]], index=['A','B','C'], columns=['c1','c2','c3'])
print(df3,'原始数据')
# 列和
print(df3.sum(),'列的和')
# 行和
print(df3.sum(axis=1),'行的和')
# 最大值与最小值
print(df3.max(),'列最大值')
print(df3.max(axis=1),'行最大值')
print(df3.min(),'列最小值')
print(df3.min(axis=1),'行最小值')
# describe描述
df3.describe()
结果:
总结:
axis
参数默认等于0,求得是列的值,当axis=1时求得是行的值,describbe()
返回的是具体一个统计的结果的表格。
三、Series和DataFrame排序
- 排序方式两种,一种是按values,一种是按index
Series实例:
s1 = Series(np.random.randn(5))
print('原始顺序',s1)
# 值排序
s2 = s1.sort_values()
print('按值升序排序',s2)
s2 = s1.sort_values(ascending=False)
print('# 按值降序排序 ',s2)
# 对index进行排序,降序同样修改ascending为False就好
print('按index升序排序',s2.sort_index())
print('按index降序排序',s2.sort_index())
结果:
DataFrame实例:
# DataFrame排序
df1 = DataFrame(np.random.randn(20).reshape(4,5), columns=['A','B','C','D','E'])
print(df1)
print("***************")
# 某一列Series升序排序
print(df1['A'].sort_values())
print("***************")
# DataFrame对某列进行排序
print(df1.sort_values('A'))
# 降序排序
print(df1.sort_values('A', ascending=False))
print("***************")
df2=df1.sort_values('A', ascending=False)
# 对index进行排序
df2.sort_index()
结果:
四、DataFrame重命名
实例:
df1 = DataFrame(np.arange(9).reshape(3,3), index=['BJ','SH','GZ'], columns=['A','B','C'])
print(df1)
print(df1.index)
print("***************")
# 方式一,直接用Series修改
df1.index = ['SZ','HZ','CQ']
print(df1.index)
print("***************")
# 方式二,使用map进行修改
print(df1.index.map(str.lower))
print("***************")
# 方式三,使用rename进行修改
print(df1.rename(index=str.upper))
print("***************")
# 同时修改行和列
df1 = df1.rename(index=str.lower, columns=str.lower)
print(df1)
print("***************")
df1.rename(index={'sz':'shenzen'}, columns={'a':'A'})
结果:
五、DataFrame的merge(合并)
-
merge()
函数常用参数有on
默认是NoNe
,on为指定列,默认情况下会自动找到相同名列,若指定了不同名列会保错,有两列以上相同的需要指定on;
how是指连接的方式,how=inner(默认),left,right,outer
实例:
df1 = DataFrame({'key':['X','Y','Z'], 'data_set1':[1,2,3]})
df2 = DataFrame({'key':['A','B','C'], 'data_set2':[4,5,6]})
# 没有相同的列值
print(pd.merge(df1,df2))
print("***************")
# 默认合并
df2 = DataFrame({'key':['X','B','C'], 'data_set_2':[4,5,6]})
print(pd.merge(df1,df2))
print("***************")
df1 = DataFrame({'key':['X','Y','Z','X'], 'data_set_1':[1,2,3,4]})
print(pd.merge(df1,df2))
print("***************")
# on为指定列,默认情况下会自动找到相同名列,若指定了不同名列会保错,有两列以上相同的需要指定on
print(pd.merge(df1,df2,on='key'))
print("*********************************************************")
# 连接的方式,how=inner(默认),left,right,outer
print(pd.merge(df1,df2,on='key',how='inner'))
print("***************")
print(pd.merge(df1,df2,on='key',how='left'))
print("***************")
print(pd.merge(df1,df2,on='key',how='right'))
print("***************")
print(pd.merge(df1,df2,on='key',how='outer'))
结果:
六、Concatenate和Combine
- Concatenate
# arrange上的Concatenate
arr1 = np.arange(9).reshape(3,3)
arr2 = np.arange(9).reshape(3,3)
# 进行concatenate,axis参数表示结合方向,默认0是纵向结合
print(np.concatenate([arr1,arr2]))#纵向
print("***************")
print(np.concatenate([arr1,arr2], axis=1))#横向
print("******************************************")
# Series上的concatenate
s1 = Series([1,2,3], index=['X','Y','Z'])
S2 = Series([4,5], index=['A','B'])
print(pd.concat([s1,S2]))#纵向
print("***************")
# 缺失值会补齐为NaN
print(pd.concat([s1,S2], axis=1))#横向
print("******************************************")
df1 = DataFrame(np.random.rand(3,3), columns=['X','Y','Z'])
df2 = DataFrame(np.random.rand(2,3), columns=['X','Y','A'])
print(pd.concat([df1,df2]))
print("***************")
print(pd.concat([df1,df2],axis=1))
结果:
- Combine
实例:
# Combine,后一个对象补齐前一个对象
# Series
s1 = Series([2,np.nan,4,np.nan], index=['A','B','C','D'])
print(s1)
print("***************")
s2 = Series([1,2,3,4], index=['A','B','C','D'])
print(s2)
print("***************")
print(s1.combine_first(s2))
print("******************************************")
df1 = DataFrame({'X':[1,np.nan,3,np.nan], 'Y':[5,np.nan,7,np.nan], 'Z':[9,np.nan,11,np.nan]})
print(df1)
print("***************")
df2 = DataFrame({'Z':[np.nan,10,np.nan,12], 'A':[1,2,3,4]})
print(df2)
print("***************")
print(df1.combine_first(df2))
结果:
七、通过apply对数据进行处理
- 首先我们读取需要的数据:
f = open('apply_demo.csv')
df = pd.read_csv(f)
df.head()
结果:
实例:
# apply传如一个函数,对某一列进行处理
# 通过分析,我们需要的是如下数据
# 定义一个处理函数
def foo(line):
items = line.strip().split(' ')
return Series([items[1], items[3], items[5]])
# 使用apply处理data列
df_temp = df['data'].apply(foo)
df_temp.head()
结果:
实例:
# 修改列名
df_temp = df_temp.rename(columns = {0:'Symbol', 1:'Seqno', 2:'Price'})
# 添加到原df中
df_new = df.combine_first(df_temp)
# 删除掉无关列并生成csv
del df_new['data'], df_new[ 'A']
#写入文件
df_new.to_csv('demo_duplicate.csv')
结果:
七、Series和DataFrame去重
- 首先读取数据结果:
实例:
df.size#查看元素数量
Out[41]: 19945
len(df)#查看数据长度
Out[42]: 3989
len(df['Seqno'].unique())#查看某列去重后的数据长度
Out[46]: 1000
# DataFrame去重,drop_dupliates
df.drop_duplicates(['Seqno'], keep='last').head()
#keep参数指定保留哪一个,默认first保留第一个,last保留最后一个
结果:
八、时间序列操作
- 首先在原有模块的基础上导入时间模块:
from datetime import datetime
*时间序列的生成
实例:
# 方式一、生成一个时间
t1 = datetime(2009, 10, 20)
print(t1)
print("***************")
#手写一个时间列表
date_list = [datetime(2016,9,1), datetime(2016,9,10), datetime(2017,9,1),datetime(2017,9,20)]
print(date_list)
print("***************")
# Series是index改为date_list
s1 = Series(np.random.rand(4), index=date_list)
print(s1)
print("***************")
# 最后查看下index 是一个DatetimeIndex
print(s1.index)
print("******************************************")
# 对Series访问,有多种写法
print(s1[datetime(2016,9,10)])
print("***************")
print(s1['2016-9-10'])
print("***************")
print(s1['20160910'])
print("***************")
# 不可以直接'201609',报错
print(s1['2016-09'])
print("******************************************")
# 方式二、pandas生成Datetime,一个开始参数,一个结束参数,periods表示数量,freq表示间隔
# 生成21个,freq默认为'D'天数
date_list = pd.date_range('2016-01-01', periods=21)
print(date_list)
print("***************")
# 修改freq,每周一
date_list = pd.date_range('2016-01-01', periods=21, freq='W-MON')
print(date_list)
print("***************")
# 间隔6小时
date_list = pd.date_range('2016-01-01','2016-02-01', freq='6H')
print(date_list)
print("***************")
# 最后设置Series的index
s2=Series(np.random.rand(28), index=date_list)
结果:
-
时间序列采样
实例:
# 生成一个时间序列
t_range = pd.date_range('2016-01-01', '2016-12-31')
# 创建Series,设置index
s1 = Series(np.random.randn(len(t_range)), index=t_range)
# 一月份取平均值
print(s1['2016-01'].mean())
print("***************")
# 对月份取平均值
s1_month = s1.resample('M').mean()
print(s1_month)
# 前填充ffill,比如一号里的没有的数据是从1月1号采取过来的
print(s1.resample('H').ffill())
print("***************")
# 后填充bfill,比如一号里的没有的数据是从1月2号采取过来的
print(s1.resample('H').bfill())
结果:
-
时间序列画图
实例:
# 画图
# 新建一个时间序列
t_range = pd.date_range('2016-01-01', '2016-12-31')
# 建立一个DataFrame
stock_df = DataFrame(index=t_range)
# 加入两行,模拟股票
stock_df['BABA'] = np.random.randint(80, 100, size=len(t_range))
stock_df['TENCENT'] = np.random.randint(30, 50, size=len(t_range))
# 显示图片,下面
stock_df.plot()
# 数据过于密集,重新清洗,按周清洗
weekly_df = DataFrame()
# resample参数w表示周分类,再取平均值
weekly_df['BABA'] = stock_df['BABA'].resample('W').mean()
weekly_df['TENCENT'] = stock_df['TENCENT'].resample('W').mean()
# 显示
weekly_df.plot()
结果:
九、数据分箱(Binning) 分组(Groupby) 聚合(Aggregation)
- 数据分箱(Binning)
实例:
# 随机生成一段成绩
score_list = np.random.randint(25, 100, size=20)
print(score_list)
print("***************")
# 进行cut分箱, bins为剪切范围
bins = [0,59,70,80,100]
print(pd.cut(score_list, bins))
print("***************")
# 查看数据,通过pd.value_counts()查看Categories数据
score_cat = pd.cut(score_list, bins)
print(pd.value_counts(score_cat))
print("***************")
# 模拟一段数据
df = DataFrame()
df['score'] = score_list
# 随机生成3个字符pd.util.testing.rands(3)
df['student'] = [pd.util.testing.rands(3) for i in range(20)]
# 对score进行分箱
print(pd.cut(df['score'], bins))
print("***************")
# 传入labels标签,进行分箱标记
df['categories'] = pd.cut(df['score'], bins, labels=['low','ok','good','great'])
df
结果:
- 数据分组
groupby()
实例:
# 打开文件
f = open('city_weather.csv')
df = pd.read_csv(f)
df
数据效果:
实例通过城市分类:
g = df.groupby(df['city'])
g.groups
效果:
其他的分组处理实例:
# 获取某一个组,以BJ为例
g.get_group('BJ')
# 对某一个组进行处理
df_bj = g.get_group('BJ')
df_bj.mean()#求BJ这一组的平均值
df_bj.describe()#返回一个详细的统计结果
# 查看整个groupby
g.mean()
# groupby可转换为列表,列表中为元组,元组中第一个值为分组名,第二个值为dataframe
list(g)
# 可以装换为字典
dict(list(g))
- 数据聚合
agg()
先看数据展示效果:
实例:
# 对df进行分组
g = df.groupby('city')
# 实验聚合函数min,求每个城市的最小值
g.agg('min')
# 自定义函数,目的查看传如函数的数据类型
# 自定义函数进行聚合
def foo (attr):
return attr.max() - attr.min()
#传入一个Sreies对象
g.agg(foo)
结果:
补充学习
# 可以对两列进行分组
g_new = df.groupby(['city', 'wind'])
g_new.groups
# 获取某一组
g_new.get_group(('BJ',2)
十、数据透视表
实例:
# 打开excel文件
xlsx = pd.ExcelFile('sales-funnel.xlsx')
df = pd.read_excel(xlsx)
# 生成透视表
# aggfunc默认取平均值
pd.pivot_table(df,index=['Name'])
实例操作:
# 可以设置多个index,多级
pd.pivot_table(df, index=['Name','Rep','Manager'])
# 多级index,经理和销售顾问
pd.pivot_table(df, index=['Manager','Rep'])
# 可以指定生成那个values
pd.pivot_table(df, index=['Manager','Rep'], values=['Price'])
# 可多个values,修改聚合函数
pd.pivot_table(df, index=['Manager','Rep'], values=['Price','Quantity'], aggfunc='sum')
# 可以添加colunms,多级columns
pd.pivot_table(df, index=['Manager','Rep'], values=['Price','Quantity'], columns=['Product'],aggfunc='sum')
# 对没有的数据赋值
df_pivot = pd.pivot_table(df, index=['Manager','Rep'], values=['Price','Quantity'], columns=['Product'],fill_value=0,aggfunc='sum')
- 总结:
pivot_table()
有多个参数,data
表示需要透视的数据,index
表示需要透视的columns
,顺序不同效果不同,aggfunc
表示聚合的函数,values
表示显示的值,fill_values
可以设置NAN的值。