Pandas 透视表、字符串向量化、时间序列

数据透视表

我们⽬前所用的累计操作都是按照⼀个维度进行,数据透视表可以看做是按照⼆维进行累计的操作功能。

# 以泰坦尼克号数据为例⼦进⾏展示
import numpy as np
import pandas as pd
import seaborn as sns
titanic = sns.load_dataset("titanic")
print(titanic.shape)
(891, 15)

数据透视表的初步使用

先进行粗分类

a = titanic.groupby("sex")[['survived']].mean()
# 可以看出,⼥性获救⽐例⼤概是男性的4倍多
print(a)
 survived
sex
female 0.742038
male 0.188908

尝试按sex,class分组,然后统计逃生人数,求mean后使用层级索引

# 可以清晰的展示出,逃⽣⼈数受sex,class 的影响
a = titanic.groupby(['sex', 'class'])['survived'].aggregate('mean').unstack()
print(a)
class First Second Third
sex
female 0.968085 0.921053 0.500000
male 0.368852 0.157407 0.135447

pivot_table

pivot_table实现的效果等同于上⼀节的管道命令,是⼀个简写。

# 尝试按sex,class分组,然后统计逃⽣⼈数,求mean后使⽤层级索引
a = titanic.pivot_table('survived', index='sex', columns='class')
print(a)
class First Second Third
sex
female 0.968085 0.921053 0.500000
male 0.368852 0.157407 0.135447

创建多级索引形状的DataFrame结果

按照sex,age,class统计,age分三个年龄段,0-18-80

# 使⽤cut函数对年龄进⾏分段
age = pd.cut(titanic['age'], [0,18,80])
a = titanic.pivot_table('survived', ['sex', age], 'class')
print(a)
class First Second Third
sex	   age
female (0, 18] 0.909091 1.000000 0.511628
	   (18, 80] 0.972973 0.900000 0.423729
male (0, 18] 0.800000 0.600000 0.215686
	 (18, 80] 0.375000 0.071429 0.133663

对列也可以使用类似策略

# 使⽤qcut对票价进⾏划分成两部分,每⼀部分⼈数相等
fare = pd.qcut(titanic['fare'], 2)
a = titanic.pivot_table('survived', ['sex', age], [fare, 'class'])
print(a)
fare (-0.001, 14.454] (14.454, 512.329] \
class First Second Third First
sex age
female (0, 18] NaN 1.000000 0.714286 0.909091
 (18, 80] NaN 0.880000 0.444444 0.972973
male (0, 18] NaN 0.000000 0.260870 0.800000
 (18, 80] 0.0 0.098039 0.125000 0.391304

fare
class 			Second Third
sex 	age
female (0, 18] 1.000000 0.318182
	   (18, 80] 0.914286 0.391304
male (0, 18] 0.818182 0.178571
	 (18, 80] 0.030303 0.192308 

字符串的向量化操作

数据科学的处理离不开字符串的处理,相应的pandas也提供了字符串向量化操作的功能,我们⼀般利用这个来对采集来的信息进行清理。

我们可以使用python的方式来处理字符串,但是⼀旦字符串中包含缺省值,此时,使用pandas的字符串向量化功能就能避免出现崩溃的情况。

import pandas as pd
strs = ['One', "Two", "Three", None, "Four"]
strs = pd.Series(strs)
print(strs)
0 One
1 Two
2 Three
3 None
4 Four
dtype: object

字符串向量化应用初步

#对字符串进⾏⼤写转换
s = strs.str.upper()
print(s)
# 对字符串进⾏⼩写转换
ss = strs.str.lower()
print("\n\n", ss)
0 ONE
1 TWO
2 THREE
3 None
4 FOUR
dtype: object

 0 one
1 two
2 three
3 None
4 four
dtype: object

其他pandas字符串方法

python中字符串的方法基本上可以直接应⽤在pandas中,需要注意的是返回值的不同,需要相应做出调整,例如判断类的返回的是⼀个bool值的数据结构,len之类的返回的是⼀个值。

相应字符串方法在需要的时候可以查看手册来使用

正则表达式

正则是字符串的大杀器,在pandas中同样也实现了正则的⼀些接⼝,如以下API:

  • match: 调用re.match, 返回bool类型内容
  • extract: 调用re.match, 返回匹配的字符串组groups
  • findall: 调用re.findall
  • replace: 正则的替换模式
  • contains: re.search,返回bool内容
  • count: 利⽤正则模式统计数量
  • split:等价于 str.split,支持正则
  • rsplit: 等价于str.rsplit,支持正则
print("strs = \n", strs)
print()
a = strs.str.extract('([O, o, n, e, N, T ]+)')
print(a)
strs =
 0 One
1 Two
2 Three
3 None
4 Four
dtype: object
 0
0 One
1 T
2 T
3 NaN
4 o

其他字符串的使用方法

pandas还提供了⼀些其他的方法来实现字符串的操作。

  • get: 获取雅安苏索引位置上的值,start=0
  • slice: 对元素进⾏切片
  • slice_replace: 对元素进行切片替换
  • cat: 连接字符串
  • repeat:重复元素
  • normalize: 将字符串转换为Unicode规范形式
  • pad: 在字符串的左边,右边或者两边增加空格
  • wrap:将字符串按照指定宽度换行
  • join: 用分隔符链接Series的每个元素
  • get_dummies: 按照分隔符提取每个元素的dummy变量,转换为one-hot编码的DataFrame
# 对slice的使⽤和函数的直接切⽚⼀个效果
# df.str.slice(2,5) 等于 df.str[2:5]
print("strs = \n", strs)
print()
a = strs.str.slice(1,4)
print(a)
print()
# 等价于
b = strs.str[1:4]
print(b)
strs =
 0 One
1 Two
2 Three
3 None
4 Four
dtype: object
0 ne
1 wo
2 hre
3 None
4 our
dtype: object
0 ne
1 wo
2 hre
3 None
4 our
dtype: object

df.str.get(i) 和 df.str[i]功能类似

# 以下案例⽤字⺟o切分字符串后选择后⾯的⼀组
a = strs.str.split('o').str.get(-1)
print(a)
0 One
1
2 Three
3 None
4 ur
dtype: object

get_dummies

如果数据中包含已经倍编码的指标(coded indicator), 可以使用get_dummies快速的把编码的信息分解。

# 假定: A=游泳, B=爬⼭, C=跑步, D=篮球
df = pd.DataFrame({'english':strs,
 'hobbies':["B|C", "A|C|D", "B|D", "A|B|C", "A|B|C|D"]})
print(df)
print()
a = df['hobbies'].str.get_dummies('|')
print(a)
 english hobbies
0 One B|C
1 Two A|C|D
2 Three B|D
3 None A|B|C
4 Four A|B|C|D
  A B C D
0 0 1 1 0
1 1 0 1 1
2 0 1 0 1
3 1 1 1 0
4 1 1 1 1

处理时间序列

Pyhton处理时间序列常用的包有datetime,dateutil,但同样也存在性能弱的问题,pandas为了处理的⼤量时间相关数据,把时间相关数据作为datetime64类型进行处理,相对来讲,这种数据类型节省内存,处理起来速度快。

在pandas中,增加了Timestamp对象,所有日期与时间的处理方法都是通过Timestamp实现。
numpy/pandas利用Timestamp和datetime64的数据类型,将python的日期处理包datetime和dateutil有机结合
起来,可以实现对日期数据的高效灵活处理。

datetime64 数据类型

datetime64是numpy处理时间相关内容的数据类型,可以对时间类型数据做灵活处理,同时还可以支持各种时间单位的操作。

常见的时间单位是:

  • Y: Year
  • M: Month
  • W: Week
  • D: Day
  • h: Hour
  • m: Minute
  • s: Second
  • ms: millisecond
  • us: micorosecond
  • ns: nanosecond
  • ps: picosecond
  • fs: femtosecond
  • as: attosecond
import numpy as np
# datetime64数据类型
date = np.array("20180-03-12", dtype=np.datetime64)
print(date)
20180-03-12

向量化操作

d = date + np.arange(5)
print(d)
['20180-03-12' '20180-03-13' '20180-03-14' '20180-03-15' '20180-03-16']

添加时间单位, 此处采用的是ns

a = np.datetime64("2019-01-13 12:45:32.30", "ns")
print(a)
2019-01-13T12:45:32.300000000

Timestamp

import pandas as pd
# 利⽤pd.to_datetime可以将多种不同的格式时间进⾏处理
date = pd.to_datetime("5th of June, 2019")
print(date)
# date可以使⽤时间格式化功能
print(date.strftime("%A"))
2019-06-05 00:00:00
Wednesday

按天计算, 进行向量化

d = date + pd.to_timedelta(np.arange(10), "D")
print(d)
DatetimeIndex(['2019-06-05', '2019-06-06', '2019-06-07', '2019-06-08',
 '2019-06-09', '2019-06-10', '2019-06-11', '2019-06-12',
 '2019-06-13', '2019-06-14'],
 dtype='datetime64[ns]', freq=None)

时间做索引

idx = pd.DatetimeIndex(['2019-01-01', '2019-02-01','2019-03-01',
 '2019-04-01','2019-05-01','2019-06-01'])
date = pd.Series(range(6), index=idx)
print(date)
2019-01-01 0
2019-02-01 1
2019-03-01 2
2019-04-01 3
2019-05-01 4
2019-06-01 5
dtype: int64

既然是索引,就可以使用来进行数据的提取

# 切片包含结束位置
print(date[ '2019-02-01':'2019-06-01'])
2019-02-01 1
2019-03-01 2
2019-04-01 3
2019-05-01 4
2019-06-01 5
dtype: int64

可以通过年份切片获取概念的全部数据

print(date["2019"])
2019-01-01 0
2019-02-01 1
2019-03-01 2
2019-04-01 3
2019-05-01 4
2019-06-01 5
dtype: int64

pandas时间序列的数据结构

pandas对时间序列准备了几个特殊的数据结构:

  • pd.DatetimeIndex: 针对时间戳数据
  • pd.PeriodIndex: 针对时间周期数据
  • pd.TimedeltaIndex: 针对时间增量或持续时间

pd.to_datetime传输⼀个时间日期会返回一个Timestamp类型数据

# 传递时间序列会返回DatetimeIndex类型数据
from datetime import datetime
dates = pd.to_datetime([datetime(2019,4,3), '5th of June, 2018', '2017-Jul-9',
 "09-02-2018", '20190105'])
# 对⼀个时间序列,会返回DatetimeIndex类型数据
print(dates)
DatetimeIndex(['2019-04-03', '2018-06-05', '2017-07-09', '2018-09-02',
 '2019-01-05'],
 dtype='datetime64[ns]', freq=None)

DatetimeIndex 类型通过 pd.to_period和⼀个频率代码可以转换成PeriodIndex类型

d = dates.to_period('D')
print(d)
PeriodIndex(['2019-04-03', '2018-06-05', '2017-07-09', '2018-09-02',
 '2019-01-05'],
 dtype='period[D]', freq='D')

当用⼀个日期减去⼀个日期,返回的是TimedeltaIndex类型

d = dates - dates[0]
print(d)
TimedeltaIndex(['0 days', '-302 days', '-633 days', '-213 days', '-88 days'],
dtype='timedelta64[ns]', freq=None)

xxx_range类函数

pandas提供了可以规律产生时间序列的函数, 此类函数的使用和range类似,pandas提供了三个函数:

  • pd.date_range: 可以处理时间戳,
  • pd.period_range:可以处理周期
  • pd.timedelta_range:可以处理时间间隔
d = pd.date_range("2018-03-03", "2018-12-02", periods=5)
print(d)
DatetimeIndex(['2018-03-03 00:00:00', '2018-05-10 12:00:00',
 '2018-07-18 00:00:00', '2018-09-24 12:00:00',
 '2018-12-02 00:00:00'],
 dtype='datetime64[ns]', freq=None)
d = pd.date_range("2018-03-03", "2018-12-02", freq="M")
print(d)
DatetimeIndex(['2018-03-31', '2018-04-30', '2018-05-31', '2018-06-30',
 '2018-07-31', '2018-08-31', '2018-09-30', '2018-10-31',
 '2018-11-30'],
 dtype='datetime64[ns]', freq='M')
d = pd.period_range("2018-01-01", periods=5, freq="M")
print(d)
PeriodIndex(['2018-01', '2018-02', '2018-03', '2018-04', '2018-05'], dtype='period[M]',
freq='M')
d = pd.timedelta_range(0, periods=5, freq="H")
print(d)
TimedeltaIndex(['00:00:00', '01:00:00', '02:00:00', '03:00:00', '04:00:00'],
dtype='timedelta64[ns]', freq='H')

你可能感兴趣的:(Pandas,简单入门,python)