数据分析之三:pandas库之基本数据结构

1. pandas的两种主要数据结构


pandas是基于NumPy的数据分析工具库,其运算功能和效率更加强大。如果说NumPy的核心数据结构是ndarray, pandas的主要数据结构分别是Series和DataFrame。pandas库的导入:

from pandas import Series, DataFrame
import pandas as pd

顾名思义, Series是一个序列,可以用作描述一个一维数组,与我们一般理解的数组不同的是,Series显式的包含了数组的下标索引列,并且这个索引列可以由我们来自定义。Series的内存模型跟ndarray类似,都是连续存储。

而DataFrame可以看成是更高级的Series,可以看成是多个Series组成的数据形式,它是以一个frame来表示数据,可以描述二维乃至更高维度的数据,它也显式的包含了二维数据的行列索引,使得数据的展示更像日程生活的表格。

依据书中介绍,DataFrame的存储结构是以一个或多个二维数据块存放的,故对矩阵的行列操作的复杂度都是相平衡的,而其他语言大部分是以一维的形式存放的(行优先或者列优先),这里先不研究具体的内存模型,考虑ndarray的连续存储模型,可以大胆猜测,DataFrame的存取效率和运算效率高于普通一维数组运算,或者说DataFrame在处理二维数据上有着天生的优势。

2. Series简单操作


  • 创建
In [68]: arr = Series([5,4,3,2,1])

# 简单赋值,索引列和数据列,最后是值的类型
In [69]: arr
Out[69]: 
0    5
1    4
2    3
3    2
4    1
dtype: int64

# 索引列
In [70]: arr.index
Out[70]: RangeIndex(start=0, stop=5, step=1)
# 值
In [71]: arr.values
Out[71]: array([5, 4, 3, 2, 1])

# 可以指定索引列,这里索引-数据必须是一一对应,否则报错
# 还有一点,我们指定的索引只是相对索引,绝对索引仍然是0,...,N-1
# 这点有点类似数据库里面的RowId
In [72]: arr = Series([5,4,3,2,1], index=['a','b','c','d','e'])

In [73]: arr
Out[73]: 
a    5
b    4
c    3
d    2
e    1
dtype: int64

# 可以使用我们熟知的np来定义
In [95]: arr = Series(randint(3,size=5))

In [96]: arr
Out[96]: 
0    0
1    2
2    1
3    1
4    2
dtype: int64

# 更可以使用json格式或者字典格式来创建
In [97]: json_str = {'a':1, 'b':2, 'c':3, 'd':4}

In [98]: arr = Series(json_str)

In [99]: arr
Out[99]: 
a    1
b    2
c    3
d    4
dtype: int64

# 我们要指定的索引列的个数也可以变化
# 多出来的列如果没有值,默认填NaN,表示此索引对应的值缺失
# 但是前面定义的时候不允许我们这样做
In [100]: idx = ['a', 'b', 'c', 'd', 'e']

In [101]: arr = Series(arr, index=idx)

In [102]: arr
Out[102]: 
a    1.0
b    2.0
c    3.0
d    4.0
e    NaN
dtype: float64
  • 存取
# 绝对索引访问
In [78]: arr[2]
Out[78]: 3
# 我们定义的相对索引访问
In [79]: arr['c']
Out[79]: 3

# 依然支持切片存取
# 使用绝对索引
In [82]: arr[0:3]
Out[82]: 
a    5
b    4
c    3
dtype: int64

# 使用相对索引
In [83]: arr['a':'c']
Out[83]: 
a    5
b    4
c    3
dtype: int64

# 取任意一组
In [86]: arr[['a','b','c']]
Out[86]: 
a    5
b    4
c    3
dtype: int64

注:使用切片时,个性化的相对索引是左右都包含的,绝对索引是右不包含,这里可能是pandas库人性化的设置,以防我们使用不规则的数据作为索引时容易失误。

索引对象的进阶以及切片的使用放到下文详细讨论。

3. DataFrame简单操作


  • 创建
# 字典方式创建
In [108]: frame_data = {'A':[1,2,3], 'B':[4,5,6], 'C':[7,8,9]}

In [109]: frame = DataFrame(frame_data)

In [110]: frame
Out[110]: 
   A  B  C
0  1  4  7
1  2  5  8
2  3  6  9

# 字典基础上,指定行索引值
In [111]: frame = DataFrame(frame_data, index=['row1', 'row2', 'row3'])

In [112]: frame
Out[112]: 
      A  B  C
row1  1  4  7
row2  2  5  8
row3  3  6  9
# 用np的矩阵来创建
In [113]: arr = np.array([[1,2,3], [4,5,6], [7,8,9]])

In [114]: arr
Out[114]: 
array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])

In [115]: frame = DataFrame(arr)

In [116]: frame
Out[116]: 
   0  1  2
0  1  2  3
1  4  5  6
2  7  8  9

# 指定行和列索引
In [120]: frame = DataFrame(arr, index=['row1', 'row2', 'row3'], columns=['col1', 'col2', 'col3'])

In [121]: frame
Out[121]: 
      col1  col2  col3
row1     1     2     3
row2     4     5     6
row3     7     8     9

# 缺失列值的填充,行的情况类似
In [124]: frame = DataFrame(frame, columns=['col1', 'col2', 'col3', 'col4'])

In [125]: frame
Out[125]: 
      col1  col2  col3  col4
row1     1     2     3   NaN
row2     4     5     6   NaN
row3     7     8     9   NaN
# 用Series来创建
In [191]: arr
Out[191]: 
0    1
1    2
2    3
dtype: int64


In [192]: frame = DataFrame([arr]*3)

In [193]: frame
Out[193]: 
   0  1  2
0  1  2  3
1  1  2  3
2  1  2  3


In [215]: frame = DataFrame({0:arr, 1:arr, 2:arr})

In [216]: frame
Out[216]: 
   0  1  2
0  1  1  1
1  2  2  2
2  3  3  3
  • 存取
# 取某一列
In [125]: frame
Out[125]: 
      col1  col2  col3  col4
row1     1     2     3   NaN
row2     4     5     6   NaN
row3     7     8     9   NaN

In [126]: frame['col2']
Out[126]: 
row1    2
row2    5
row3    8
Name: col2, dtype: int64
# 使用切片索引获取行
In [135]: frame[0:3]
Out[135]: 
      col1  col2  col3  col4
row1     1     2     3   NaN
row2     4     5     6   NaN
row3     7     8     9   NaN

In [136]: frame[0:2]
Out[136]: 
      col1  col2  col3  col4
row1     1     2     3   NaN
row2     4     5     6   NaN

# 也可以使用ix获取
In [138]: frame.ix[0]
Out[138]: 
col1    1.0
col2    2.0
col3    3.0
col4    NaN
Name: row1, dtype: float64

In [139]: frame.ix['row1']
Out[139]: 
col1    1.0
col2    2.0
col3    3.0
col4    NaN
Name: row1, dtype: float64

# 获取任意行
In [140]: frame.ix[[0,1]]
Out[140]: 
      col1  col2  col3  col4
row1     1     2     3   NaN
row2     4     5     6   NaN
# 获取任意行、任意列
In [142]: frame.ix[[0, 1]][['col1', 'col2']]
Out[142]: 
      col1  col2
row1     1     2
row2     4     5
  • 行列存取效率的比较
# 获取任意一列的时间
In [162]: frame['col2']
Out[162]: 
row1    2
row2    5
row3    8
Name: col2, dtype: int64

In [163]: %timeit frame['col2']
The slowest run took 19.52 times longer than the fastest. This could mean that an intermediate result is being cached.
100000 loops, best of 3: 2.36 µs per loop
# 获取任意一行的时间
In [164]: frame.ix['row1']
Out[164]: 
col1    1.0
col2    2.0
col3    3.0
col4    NaN
Name: row1, dtype: float64

In [165]: %timeit frame.ix['row1']
10000 loops, best of 3: 133 µs per loop

#切片方式获取一行或多行的时间
In [167]: %timeit frame[0:1]
The slowest run took 5.04 times longer than the fastest. This could mean that an intermediate result is being cached.
10000 loops, best of 3: 92.8 µs per loop
# 获取某个“数据块”的时间
In [170]: frame.ix[[0,1]][['col1', 'col2']]
Out[170]: 
      col1  col2
row1     1     2
row2     4     5

In [171]: %timeit frame.ix[[0,1]][['col1', 'col2']]
1000 loops, best of 3: 881 µs per loop

由此,可以看出,DataFrame不同方式的读取速度:列 > 行 > 数据块,这里验证了DataFrame由Series组成,以Series为单位来存取效率会更高。

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

推荐阅读更多精彩内容