数据分析(3)--Pandas数据处理

一、概述

前面我们学习了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)

结果:

image.png

补充学习

# 可以对两列进行分组
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的值。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,634评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,951评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,427评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,770评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,835评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,799评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,768评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,544评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,979评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,271评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,427评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,121评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,756评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,375评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,579评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,410评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,315评论 2 352

推荐阅读更多精彩内容