在进行科学计算中,pandas 它是一个核心包,里面有很多其他包的功能。
目录
# 设置为 inline 风格
%matplotlib inline
# 包导入
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
数据整形
tuples = list(zip(*[['bar', 'bar', 'baz', 'baz',
'foo', 'foo', 'qux', 'qux'],
['one', 'two', 'one', 'two',
'one', 'two', 'one', 'two']]))
index = pd.MultiIndex.from_tuples(tuples, names=['first', 'second'])
df = pd.DataFrame(np.random.randn(8, 2), index=index, columns=['A', 'B'])
df
数据透视表
df = pd.DataFrame({'A' : ['one', 'one', 'two', 'three'] * 3,
'B' : ['A', 'B', 'C'] * 4,
'C' : ['foo', 'foo', 'foo', 'bar', 'bar', 'bar'] * 2,
'D' : np.random.randn(12),
'E' : np.random.randn(12)})
df
pd.pivot_table(df, values='D', index=['A', 'B'], columns=['C'])#数据透视表
C bar foo
A B
one A 0.794017 1.477533
B 1.709597 0.019528
C -0.658155 0.806713
three A 0.502807 NaN
B NaN -0.067922
C 0.464731 NaN
two A NaN 0.007806
B -0.532554 NaN
C NaN -0.912452
时间序列
pandas 提供了强大的时间序列功能,比如把秒级的股票数据转换为5分钟周期数据等。
核心数据结构
Series
Series 是一维带标签的数组,数组里可以放任意的数据(整数,浮点数,字符串,Python Object)。其基本的创建函数是:
s = pd.Series(data, index=index)
其中 index 是一个列表,用来作为数据的标签。data 可以是不同的数据类型:
- Python 字典
- ndarray 对象
- 一个标量值,如 5
ndarray 对象是用于存放同类型元素的多维数组。darray 对象由计算机内存的连续一维部分组成,并结合索引模式,将每个元素映射到内存块中的一个位置。内存块以行顺序(C样式)或列顺序(FORTRAN或MatLab风格,即前述的F样式)来保存元素。
从 ndaray 创建
#random.randn(5)表示[0-1)的小数,并且符合正态分布
s = pd.Series(np.random.randn(5), index=['a', 'b', 'c', 'd', 'e'])#索引
s
a 0.747292
b -1.120276
c -0.132692
d -0.267813
e -0.590904
dtype: float64
s.index
Index([u'a', u'b', u'c', u'd', u'e'], dtype='object')
从字典创建
# 空值的默认处理
d = {'a' : 0., 'b' : 1., 'd' : 3}
s = pd.Series(d, index=list('abcd'))
s
a 0
b 1
c NaN
d 3
dtype: float64
从标量创建
pd.Series(3, index=list('abcde'))
a 3
b 3
c 3
d 3
e 3
dtype: int64
Series 是类 ndarray 对象
s = pd.Series(np.random.randn(5))
s
0 0.882069
1 -0.134360
2 -0.925088
3 0.191072
4 2.546704
dtype: float64
s[[1, 3, 4]]
1 -0.134360
3 0.191072
4 2.546704
dtype: float64
np.exp(s)
0 2.415892
1 0.874275
2 0.396497
3 1.210546
4 12.764963
dtype: float64
np.sin(s)
0 0.772055
1 -0.133957
2 -0.798673
3 0.189911
4 0.560416
dtype: float64
Series 是类字典对象
s = pd.Series(np.random.randn(5), index=['a', 'b', 'c', 'd', 'e'])
s
a -2.149840
b -0.924115
c 0.481231
d 1.033813
e -0.462794
dtype: float64
标签对齐操作
s1 = pd.Series(np.random.randn(3), index=['a', 'c', 'e'])
s2 = pd.Series(np.random.randn(3), index=['a', 'd', 'e'])
print '{0}\n\n{1}'.format(s1, s2)
a -0.917905
c -0.744616
e 0.114522
dtype: float64
a 0.721087
d -0.471575
e 0.796093
dtype: float64
name 属性
s = pd.Series(np.random.randn(5), name='Some Thing')
s
0 0.623787
1 0.517239
2 1.551314
3 1.414463
4 -1.224611
Name: Some Thing, dtype: float64
s.name
'Some Thing'
DataFrame
DataFrame 是二维带行标签和列标签的数组。可以把 DataFrame 想你成一个 Excel 表格或一个 SQL 数据库的表格,还可以相像成是一个 Series 对象字典。它是 Pandas 里最常用的数据结构。
创建 DataFrame 的基本格式是:
df = pd.DataFrame(data, index=index, columns=columns)
其中 index 是行标签,columns 是列标签,data 可以是下面的数据:
- 由一维 numpy 数组,list,Series 构成的字典
- 二维 numpy 数组
- 一个 Series
- 另外的 DataFrame 对象
从字典创建
d = {'one' : pd.Series([1, 2, 3], index=['a', 'b', 'c']),
'two' : pd.Series([1, 2, 3, 4], index=['a', 'b', 'c', 'd'])}
pd.DataFrame(d)
one two
a 1 1
b 2 2
c 3 3
d NaN 4
pd.DataFrame(d, index=['d', 'b', 'a'])
one two
d NaN 4
b 2 2
a 1 1
pd.DataFrame(d, index=['d', 'b', 'a'], columns=['two', 'three'])
two three
d 4 NaN
b 2 NaN
a 1 NaN
d = {'one' : [1, 2, 3, 4],
'two' : [21, 22, 23, 24]}
pd.DataFrame(d)
one two
0 1 21
1 2 22
2 3 23
3 4 24
pd.DataFrame(d, index=['a', 'b', 'c', 'd'])
one two
a 1 21
b 2 22
c 3 23
d 4 24
从结构化数据中创建
data = [(1, 2.2, 'Hello'), (2, 3., "World")]
pd.DataFrame(data)
0 1 2
0 1 2.2 Hello
1 2 3.0 World
pd.DataFrame(data, index=['first', 'second'], columns=['A', 'B', 'C'])
A B C
first 1 2.2 Hello
second 2 3.0 World
从元组字典创建
了解其创建的原理,实际应用中,会通过数据清洗的方式,把数据整理成方便 Pandas 导入且可读性好的格式。最后再通过 reindex/groupby 等方式转换成复杂数据结构。
d = {('a', 'b'): {('A', 'B'): 1, ('A', 'C'): 2},
('a', 'a'): {('A', 'C'): 3, ('A', 'B'): 4},
('a', 'c'): {('A', 'B'): 5, ('A', 'C'): 6},
('b', 'a'): {('A', 'C'): 7, ('A', 'B'): 8},
('b', 'b'): {('A', 'D'): 9, ('A', 'B'): 10}}
# 多级标签
pd.DataFrame(d)
a b
a b c a b
A B 4 1 5 8 10
C 3 2 6 7 NaN
D NaN NaN NaN NaN 9
从 Series 创建
s = pd.Series(np.random.randn(5), index=['a', 'b', 'c', 'd', 'e'])
pd.DataFrame(s)
0
a -0.789343
b 0.127384
c 1.084005
d -0.755011
e -0.963299
列选择/增加/删除
df = pd.DataFrame(np.random.randn(6, 4), columns=['one', 'two', 'three', 'four'])
df
one two three four
0 2.045300 -0.981722 -0.656081 -0.639517
1 -0.550780 0.248781 -0.146424 0.217392
2 1.702775 0.103998 -0.662138 -0.534071
3 -2.035681 0.015025 1.368209 0.178378
4 -1.092208 0.091108 -0.892496 -0.611198
5 0.093502 0.267428 1.189654 -0.258723
# 指定插入位置
df.insert(1, 'bar', df['one'])
df
索引和选择
对应的操作,语法和返回结果
- 选择一列 -> df[col] -> Series
- 根据行标签选择一行 -> df.loc[label] -> Series
- 根据行位置选择一行 -> df.iloc[label] -> Series
- 选择多行 -> df[5:10] -> DataFrame
- 根据布尔向量选择多行 -> df[bool_vector] -> DataFrame
Panel
Panel 是三维带标签的数组。实际上,Pandas 的名称由来就是由 Panel 演进的,即 pan(el)-da(ta)-s。Panel 比较少用,但依然是最重要的基础数据结构之一。
- items: 坐标轴 0,索引对应的元素是一个 DataFrame
- major_axis: 坐标轴 1, DataFrame 里的行标签
- minor_axis: 坐标轴 2, DataFrame 里的列标签
电影数据分析
准备工作
从网站 grouplens.org/datasets/movielens 下载 MovieLens 1M Dataset 数据。
数据说明
参阅数据介绍文件 README.txt
利用 Pandas 分析电影评分数据
- 数据读取
- 数据合并
- 统计电影平均得分
- 统计活跃电影 -> 获得评分的次数越多说明电影越活跃
- 女生最喜欢的电影排行榜
- 男生最喜欢的电影排行榜
- 男女生评分差距最大的电影 -> 某类电影女生喜欢,但男生不喜欢
- 最具争议的电影排行榜 -> 评分的方差最大
数据读取
user_names = ['user_id', 'gender', 'age', 'occupation', 'zip']
users = pd.read_table('ml-1m/users.dat', sep='::', header=None, names=user_names, engine='python')
rating_names = ['user_id', 'movie_id', 'rating', 'timestamp']
ratings = pd.read_table('ml-1m/ratings.dat', sep='::', header=None, names=rating_names, engine='python')
movie_names = ['movie_id', 'title', 'genres']
movies = pd.read_table('ml-1m/movies.dat', sep='::', header=None, names=movie_names, engine='python')
数据合并
data = pd.merge(pd.merge(users, ratings), movies)
len(data)
data.head(5)
user_id gender age occupation zip movie_id rating timestamp title genres
0 1 F 1 10 48067 1193 5 978300760 One Flew Over the Cuckoo's Nest (1975) Drama
1 2 M 56 16 70072 1193 5 978298413 One Flew Over the Cuckoo's Nest (1975) Drama
2 12 M 25 12 32793 1193 4 978220179 One Flew Over the Cuckoo's Nest (1975) Drama
3 15 M 25 7 22903 1193 4 978199279 One Flew Over the Cuckoo's Nest (1975) Drama
4 17 M 50 1 95350 1193 5 978158471 One Flew Over the Cuckoo's Nest (1975) Drama
# 按性别查看各个电影的平均评分
# 按性别查看各个电影的平均评分
mean_ratings_gender = data.pivot_table(values='rating', index='title', columns='gender', aggfunc='mean')
mean_ratings_gender.head(5)
# 活跃电影排行榜
ratings_by_movie_title = data.groupby('title').size()
ratings_by_movie_title.head(5)