pandas数据结构

pandas数据结构

这里需要谨记两点

pandas是基于numpy构建的。
pandas的数据结构实际上和Excel是一致的。

为什么这样说第二点呢?

因为在我看来,它的数据结构可以这样理解。

Series就相当于Excel的一列,有对应的行号。
DataFrame就相当于Excel表格,有行,有列,每一列还可以是不同的数据类型。
索引对象,就是这些行号,列号,以及Excel中绝对引用与相对引用。

如果按照上面这样想,就很容易理解了。

Series

创建

Series有一组数据(各种numpy数据类型)以及与之相关的数据标签(索引组成)。

就相当于Excel中的一列以及对应的行号。


In [1]: import numpy as np

In [2]: import pandas as pd

In [3]: from pandas import Series,DataFrame

In [4]: ser = Series([-2,-4,3,-1,5])

In [5]: ser
Out[5]:
0   -2
1   -4
2    3
3   -1
4    5
dtype: int64

可以看到,Series与Excel的表格中的某列,极其相似,索引在左,值在右。

这里的0,1,...4是Series自动创建的索引。

这也说明,如果我们不指定索引,那么Series会自动为数据值创建一个0-(N-1)(N为数据长度)的整数型索引。

不过,Series支持我们指定索引,通过index参数。


In [7]: ser2 =  Series([-2,-4,3,-1,5],index=['d','a','c','b','e'])

In [8]: ser2
Out[8]:
d   -2
a   -4
c    3
b   -1
e    5
dtype: int64

我们可以通过Series的属性valuesindex来查看数组及其索引。


In [9]: ser2.values#查看数组形式
Out[9]: array([-2, -4,  3, -1,  5], dtype=int64)

In [10]: ser2.index#查看索引
Out[10]: Index(['d', 'a', 'c', 'b', 'e'], dtype='object')

赋值

还可通过索引赋值,取值,赋给不存在的索引值会添加一个新值。


In [11]: ser2['c'] #取单值
Out[11]: 3

In [12]: ser2['b'] = 12#赋值

In [13]: ser2 
Out[13]:
d    -2
a    -4
c     3
b    12
e     5
dtype: int64

In [14]: ser2['f'] = 10 #添加新值

In [16]: ser2[['c','b','f','a']] #取出一组值
Out[16]:
c     3
b    12
f    10
a    -4
dtype: int64

我们还可以复制的方式来更改索引


In [43]: ser.index = ['one','two','three','four','five']

In [44]: ser
Out[44]:
one     -2
two     -4
three    3
four    -1
five     5
dtype: int64

字典创建

其实,正常的想法应该是将Series看做一个有序字典,因为很显然通过上面的实验我们可以发现,它也是索引值到数据值的映射。因此它可以用在字典函数中。

In [17]: 'b' in ser2
Out[17]: True

In [18]: 'g' in ser2
Out[18]: False

故,可以用字典来创建Series。


In [19]: zidian = {'nihao':2000,'wobuhao':2300,'hahah':3020,'niqu':4300}#字典

In [20]: ser3 = Series(zidian)#创建Series

In [21]: ser3
Out[21]:
hahah      3020
nihao      2000
niqu       4300
wobuhao    2300
dtype: int64

可以注意到

字典的键就是Series中的索引,而且还会有序排列。


In [29]: suoyin = ['jiushi','nihao','niqu','wobuhao']
In [30]: ser4 = Series(zidian,index = suoyin)
In [31]: ser4
Out[31]:
jiushi        NaN
nihao      2000.0
niqu       4300.0
wobuhao    2300.0
dtype: float64

在上面这个实验中可以发现,

我们指定了索引,zidian中与suoyin相匹配的值被取了出来,而jiushi没有值,匹配不到,因此结果为NaN。

NaN(not a number)非数字,它表示缺失或NA值

缺失(mising)或NA表示缺失数据。

pandas中的isnullnotnull函数用于检测缺失数据。Series也有类似的示例方法。

In [32]: pd.isnull(ser4)
Out[32]:
jiushi      True
nihao      False
niqu       False
wobuhao    False
dtype: bool

In [33]: pd.notnull(ser4)
Out[33]:
jiushi     False
nihao       True
niqu        True
wobuhao     True
dtype: bool


In [34]: ser4.isnull()
Out[34]:
jiushi      True
nihao      False
niqu       False
wobuhao    False
dtype: bool

In [35]: ser4.notnull()
Out[35]:
jiushi     False
nihao       True
niqu        True
wobuhao     True
dtype: bool

置于缺失数据怎样处理,我们以后在讨论。

数组运算

numpy的数组运算都可以应用到Series。

In [26]: ser[ser > 0] # 布尔数组过滤
Out[26]:
2    3
4    5
dtype: int64

In [27]: ser * 2 #标量运算
Out[27]:
0    -4
1    -8
2     6
3    -2
4    10
dtype: int64

In [28]: np.exp(ser) # 应用数学函数
Out[28]:
0      0.135335
1      0.018316
2     20.085537
3      0.367879
4    148.413159
dtype: float64

In [36]: ser3
Out[36]:
hahah      3020
nihao      2000
niqu       4300
wobuhao    2300
dtype: int64

In [37]: ser4
Out[37]:
jiushi        NaN
nihao      2000.0
niqu       4300.0
wobuhao    2300.0
dtype: float64

In [38]: ser3 + ser4 #两个Series相加
Out[38]:
hahah         NaN
jiushi        NaN
nihao      4000.0
niqu       8600.0
wobuhao    4600.0
dtype: float64

可以注意到:
索引与值之间的连接一直被保留
值会变,索引不会变

联想下Excel,不论做什么运算,行号是不会变得。
两个Series相加也类似于Excel中的合并计算。


Series对象本身和索引还有一个name属性。

In [39]: ser4.naem = 'test'#name属性

In [40]: ser4.index.name = 'number'#name属性

In [41]: ser4
Out[41]:
number
jiushi        NaN
nihao      2000.0
niqu       4300.0
wobuhao    2300.0
dtype: float64

ser2.name = 'test'

ser2.index.naem = 'pop'

ser2
Out[10]: 
d   -2
a   -4
c    3
b   -1
e    5
Name: test, dtype: int64

DataFrame

DataFrame就是一个表个性的数据结构,它基本和Excel是一样的。有行索引(行号),列索引(列号)。
它对行和列的操作基本一致。
也可以看成由Series组成的字典。

创建

  1. 通过传入等长列表组成的字典。
  2. 传入numpy数组组成的字典。

In [3]: data = {'date':[2015,2012,2000,2013,2016],'city':['haerbin','beijing','tianjin','shijiazhuang','jinan'],'shuju':[1.2,1.3,1.4,2.3,2.7]}#等长列表字典

In [4]: frame = DataFrame(data)

In [5]: frame
Out[5]:
           city  date  shuju
0       haerbin  2015    1.2
1       beijing  2012    1.3
2       tianjin  2000    1.4
3  shijiazhuang  2013    2.3
4         jinan  2016    2.7

In [6]: frame1 = DataFrame(np.random.randn(16).reshape(4,4))#numpy数组

In [7]: frame1
Out[7]:
          0         1         2         3
0 -0.077134  0.983138 -0.483991 -1.107506
1 -1.721202  0.057802  0.090921  0.411377
2 -1.973126  1.335374 -0.524562  0.017366
3 -0.311434  1.819138 -0.258790 -0.663582

可以注意到,DataFrame会像Series一样自动的加上索引,且全部列会被有序排列

我们也可以指定列的顺序(行也是适用的)。


In [8]: DataFrame(data,columns=['date','city','shuju'])
Out[8]:
   date          city  shuju
0  2015       haerbin    1.2
1  2012       beijing    1.3
2  2000       tianjin    1.4
3  2013  shijiazhuang    2.3
4  2016         jinan    2.7

与Series一样,如果,我们指定的列在数据中不存在,也会产生NA值。
这就相当于,有列名,但是没有对应的值。

In [12]: frame2 = DataFrame(data,columns=['date','city','shuju','nohere'],index = ['one','two','three','four','five'])

In [13]: frame2
Out[13]:
       date          city  shuju nohere
one    2015       haerbin    1.2    NaN
two    2012       beijing    1.3    NaN
three  2000       tianjin    1.4    NaN
four   2013  shijiazhuang    2.3    NaN
five   2016         jinan    2.7    NaN

In [14]: frame2.columns
Out[14]: Index(['date', 'city', 'shuju', 'nohere'], dtype='object')

但是,指定了six行的话就会返回错误,因为数据比我们的行少。

索引

我们可以通过字典或者属性的方式来获得一个Series。

列索引


In [15]: frame2['city'] #字典方式
Out[15]:
one           haerbin
two           beijing
three         tianjin
four     shijiazhuang
five            jinan
Name: city, dtype: object

In [16]: frame2.city #属性方式
Out[16]:
one           haerbin
two           beijing
three         tianjin
four     shijiazhuang
five            jinan
Name: city, dtype: object

In [27]: frame2[['date','shuju']]#两列
Out[27]:
       date  shuju
one    2015    1.2
two    2012    1.3
three  2000    1.4
four   2013    2.3
five   2016    2.7

In [28]: frame2[[0,1,2]]#索引号
Out[28]:
       date          city  shuju
one    2015       haerbin    1.2
two    2012       beijing    1.3
three  2000       tianjin    1.4
four   2013  shijiazhuang    2.3
five   2016         jinan    2.7

In [29]: frame2[[1:2]]#切片
  File "<ipython-input-29-756d0bb4bbed>", line 1
    frame2[[1:2]]
             ^
SyntaxError: invalid syntax

通过以上代码,我们可以知道DataFrame与Series的索引是相同的。这样获取Series的话,其name属性也被设置好了。

另外,发现DataFrame的列也是存在索引号的。
切片的方法也是行不通的,会返回错误

行索引

至于行的获取我们可以通过位置或者名称的方式。如索引字段ix。

还有其他方法,如:

  1. 类似列表切片,可以看到器索引也是从0开始。
  2. 按照指定的索引选择一行或多行,使用函数.loc[]
  3. 指定位置来选择一行或多行,使用.ioc[]
In [18]: frame2.ix['three']
Out[18]:
date         2000
city      tianjin
shuju         1.4
nohere        NaN
Name: three, dtype: object

#此文,不是同一天写的

In [6]: frame2[0:2]#类似于列表切片
Out[6]:
     date     city  shuju nohere
one  2015  haerbin    1.2    NaN
two  2012  beijing    1.3    NaN

In [12]: frame2[:-2]#类似于列表切片
Out[12]:
       date     city  shuju nohere
one    2015  haerbin    1.2    NaN
two    2012  beijing    1.3    NaN
three  2000  tianjin    1.4    NaN

In [13]: frame2[-4:-2]#类似于列表切片
Out[13]:
       date     city  shuju nohere
two    2012  beijing    1.3    NaN
three  2000  tianjin    1.4    NaN

In [18]: frame2.loc['one']#.loc来选定一行
Out[18]:
date         2015
city      haerbin
shuju         1.2
nohere        NaN
Name: one, dtype: object

In [20]: frame2.loc['one':'three']#.loc选定多行
Out[20]:
       date     city  shuju nohere
one    2015  haerbin    1.2    NaN
two    2012  beijing    1.3    NaN
three  2000  tianjin    1.4    NaN

可以发现,行索引是可以进行切片的,列是不可以的,具体的索引方法使用,这里就不仔细研究了,因为这里不是重点。

列赋值

可以直接给列进行赋值,这里需要用到索引。


In [35]: frame2['nowhere'] = 1.5

In [36]: frame2
Out[36]:
       date          city  shuju nohere  nowhere
one    2015       haerbin    1.2    NaN      1.5
two    2012       beijing    1.3    NaN      1.5
three  2000       tianjin    1.4    NaN      1.5
four   2013  shijiazhuang    2.3    NaN      1.5
five   2016         jinan    2.7    NaN      1.5

In [37]: frame2.nowhere = 2

In [38]: frame2
Out[38]:
       date          city  shuju nohere  nowhere
one    2015       haerbin    1.2    NaN        2
two    2012       beijing    1.3    NaN        2
three  2000       tianjin    1.4    NaN        2
four   2013  shijiazhuang    2.3    NaN        2
five   2016         jinan    2.7    NaN        2

In [39]: frame2['nowhere'] = np.arange(5.0)

In [40]: frame2
Out[40]:
       date          city  shuju nohere  nowhere
one    2015       haerbin    1.2    NaN      0.0
two    2012       beijing    1.3    NaN      1.0
three  2000       tianjin    1.4    NaN      2.0
four   2013  shijiazhuang    2.3    NaN      3.0
five   2016         jinan    2.7    NaN      4.0

In [41]: frame2.nowhere = np.arange(5.0,10.0)

In [42]: frame2
Out[42]:
       date          city  shuju nohere  nowhere
one    2015       haerbin    1.2    NaN      5.0
two    2012       beijing    1.3    NaN      6.0
three  2000       tianjin    1.4    NaN      7.0
four   2013  shijiazhuang    2.3    NaN      8.0
five   2016         jinan    2.7    NaN      9.0

In [43]: frame2.nowhere = [1,2,3,4,5,6]

ValueError: Length of values does not match length of index

将列表或数组赋值给某列时,其长度必须与DataFrame的列的长度匹配,如果将Series赋值给DataFrame,则其会与DataFrame的索引精确匹配,如果有空位,则空位是缺失值。


In [44]: x = Series([12, 1.7, 1.9],index = ['one','four','three'])#Sereies

In [45]: frame2.nowhere = x #将Series赋值给frame2的nowhere

In [46]: frame2
Out[46]:
       date          city  shuju nohere  nowhere
one    2015       haerbin    1.2    NaN     12.0
two    2012       beijing    1.3    NaN      NaN
three  2000       tianjin    1.4    NaN      1.9
four   2013  shijiazhuang    2.3    NaN      1.7
five   2016         jinan    2.7    NaN      NaN

为不存在的列赋值,会创建这个不存在的列。del是关键字,他可以用来删除列


In [53]: frame2['wu'] = frame2.city == 'tianjin'

In [54]: frame2
Out[54]:
       date          city  shuju nohere  nowhere     wu
one    2015       haerbin    1.2    NaN     12.0  False
two    2012       beijing    1.3    NaN      NaN  False
three  2000       tianjin    1.4    NaN      1.9   True
four   2013  shijiazhuang    2.3    NaN      1.7  False
five   2016         jinan    2.7    NaN      NaN  False

In [57]: del frame2['wu']#删除列

In [58]: frame2
Out[58]:
       date          city  shuju nohere  nowhere
one    2015       haerbin    1.2    NaN     12.0
two    2012       beijing    1.3    NaN      NaN
three  2000       tianjin    1.4    NaN      1.9
four   2013  shijiazhuang    2.3    NaN      1.7
five   2016         jinan    2.7    NaN      NaN

In [59]: frame2.columns#查看列
Out[59]: Index(['date', 'city', 'shuju', 'nohere', 'nowhere'], dtype='object')

经过试验,发现在这里使用frame2.wu的索引方式结果不变,也就是说这种方法在这里行不通,因此,最好使用上方代码块的方式。

我们还需要知道的是,对与索引所返回的Series所做的任何更改都会反映到DataFrame上面。

DataFrame还可以接受嵌套字典,也就是字典的字典。外层字典的键作为列,内层键则作为行的索引。

属性

我们可以设置DataFrame的index和columns属性,也就是行和列的属性。


In [60]: frame2.index.name = 'year'

In [61]: frame2.columns.name = 'state'

In [62]: frame2
Out[62]:
state  date          city  shuju nohere  nowhere
year
one    2015       haerbin    1.2    NaN     12.0
two    2012       beijing    1.3    NaN      NaN
three  2000       tianjin    1.4    NaN      1.9
four   2013  shijiazhuang    2.3    NaN      1.7
five   2016         jinan    2.7    NaN      NaN

DataFrame的values属性与Series一样,都会以二维数组形式返回。


In [63]: frame2.values
Out[63]:
array([[2015, 'haerbin', 1.2, nan, 12.0],
       [2012, 'beijing', 1.3, nan, nan],
       [2000, 'tianjin', 1.4, nan, 1.9],
       [2013, 'shijiazhuang', 2.3, nan, 1.7],
       [2016, 'jinan', 2.7, nan, nan]], dtype=object)

可以看到dtype的类型是object,这是因为其各列的数据类型不同,因此返回了一个可以兼容所有列的数值类型。

索引

上方我们已经说了很久的索引对象,索引对象最大的特点是不可修改性(immutable)


In [64]: inde = frame2.index

In [65]: inde
Out[65]: Index(['one', 'two', 'three', 'four', 'five'], dtype='object', name='year')

In [66]: inde[1]
Out[66]: 'two'

In [67]: inde[1] = 'hah'
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-67-79c2a592e832> in <module>()
----> 1 inde[1] = 'hah'

D:\Users\sunshine\Anaconda\lib\site-packages\pandas\indexes\base.py in __setitem__(self, key, value)
   1402
   1403     def __setitem__(self, key, value):
-> 1404         raise TypeError("Index does not support mutable operations")
   1405
   1406     def __getitem__(self, key):

TypeError: Index does not support mutable operations

判断某一行或者某一列是否在索引中。

In [70]: 'city' in frame2.columns
Out[70]: True

In [71]: 'three' in frame2.index
Out[71]: True

除此之外,index还存在很多方法和属性。

索引方法和属性 说明
append 链接额外的索引对象,产生一个新的索引
diff 计算索引的差集
intersection 计算交集
union 计算并集
isin 计算出一个布尔数组表示每一个值是否包含在所传递的集合里
delete 计算删除位置i的元素的索引
drop 计算删除所传递的值后的索引
insert 计算在位置i插入元素后的索引
is_monotonic 返回True,如果每一个元素都比它前面的元素大或相等
is_unique 返回True,如果索引没有重复的值
unique 计算索引的唯一值数组
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,902评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,037评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,978评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,867评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,763评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,104评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,565评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,236评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,379评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,313评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,363评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,034评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,637评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,719评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,952评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,371评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,948评论 2 341

推荐阅读更多精彩内容