pandas数据结构

亡梦爱人 提交于 2019-12-03 08:53:10

1pandas数据结构介绍

pandas有两大常用的工具数据结构:Series和DataFrame。

1.1Series

Series是一种一维的数组型对象,它包含了一个值序列,并且包含了数据标签,称为索引(index)。最简单的序列可以仅仅由一个数组形成:

import pandas as pd
obj = pd.Series([4,3,5,6])
print(obj)
--------------------------
0    4
1    3
2    5
3    6
dtype: int64

从中我们可以看到索引在左边,值在右边。由于我们不为数组指定索引,默认生成的索引是从0带N-1(N是数组的长度)。我们可以通过values属性和index属性分别获得Series对象的值和索引:

print(obj.values) #[4 3 5 6]
print(obj.index) #RangeIndex(start=0, stop=4, step=1)

通常需要一个索引序列,用标签标识每个数据点:

obj = pd.Series([4,7,-5,3],index = ['d','b','a','c'])
print(obj)
-----------------------------------------------------
d    4
b    7
a   -5
c    3
dtype: int64
print(obj.index) #Index(['d', 'b', 'a', 'c'], dtype='object')

我们可以在从数据中选择数据的时候使用标签来进行索引:

print(obj['a']) #-5
print(obj['d']) #4
print(obj[['c','a','b']])
-------------------------
c    3
a   -5
b    7
dtype: int64

上面的例子中,[‘c’,‘a’,‘d’]包含的不是数字而是字符串,作为索引列表。
使用NumPy的函数或NumPy风格的操作,比如使用布尔值数组进行过滤,与标量相乘,或是应用数学函数,这些操作将保存索引值连接:

print(obj[obj > 0])
-------------------
d    4
b    7
c    3
dtype: int64
print(obj * 2)
-------------------
d     8
b    14
a   -10
c     6
dtype: int64
print(np.exp(obj))
-------------------
d      54.598150
b    1096.633158
a       0.006738
c      20.085537
dtype: float64

从另一个角度考虑Series,可以认为它是一个长度固定且有序的字典,因为它将索引值和数据值按位置配对:

print('b' in obj) #True
print('e' in obj) #False

我们可以使用字典生成一个Series:

sdata = {'Ohio':35000,'Texas':71000,'Oregon':16000,'Utah':5000}
obj = pd.Series(sdata)
print(obj)
----------------------
Ohio      35000
Texas     71000
Oregon    16000
Utah       5000
dtype: int64

当我们把字典传递给Series构造函数时,产生的Series的索引将是排序好的字典键。我们可以将字典键按照我们所想要的顺序传递给构造函数:

sdata = {'Ohio':35000,'Texas':71000,'Oregon':16000,'Utah':5000}
states = ['California','Ohio','Oregon','Texas']
obj = pd.Series(sdata,index = states)
print(obj)
-------------------------------------
California        NaN
Ohio          35000.0
Oregon        16000.0
Texas         71000.0
dtype: float64

上面的例子中,sdata中的三个值被放置在正确的位置,但是因为’California’没有出现在sdata的键中,它对应的值是NaN(not a number),这是pandas中标记缺失值或NA值的方式。
pandas中使用isnull和notnull函数来检查缺失数据:

print(pd.isnull(obj))
---------------------
California     True
Ohio          False
Oregon        False
Texas         False
dtype: bool
print(pd.notnull(obj))
---------------------
California    False
Ohio           True
Oregon         True
Texas          True
dtype: bool

isnull和notnull也是Series的实例方法:

print(obj.isnull())
-------------------
California     True
Ohio          False
Oregon        False
Texas         False
dtype: bool

Series对象自身和其索引都有name属性,这个特性与pandas其他重要功能集成在一起:

obj.name = 'population'
obj.index.name = 'state'
print(obj)
--------------------------------
state
California        NaN
Ohio          35000.0
Oregon        16000.0
Texas         71000.0
Name: population, dtype: float64

Series的索引可以通过按位置赋值的方式进行改变:

obj.index = [0,1,2,3]
print(obj)
--------------------------------
0        NaN
1    35000.0
2    16000.0
3    71000.0
Name: population, dtype: float64

1.2DataFrame

DataFrame表示的是矩阵的数据表,它包含已排序的列集合,每一列可以是不同的值类型(数值、字符串、布尔值等)。DataFrame既有行索引也有列索引,它可以被视为一个共享相同索引的Series的字典。在DataFrame中,数据被存储为一个以上的二维块,而不是列表、字典或其他一维数组的组合。尽管DataFrame是二维的,但是我们可以利用分层索引在DataFrame中展现更高维度的数据。
有多种方式可以构建DataFrame,其中最常用的方式是利用包含等长度列表或NumPy数组的字典来形成DataFrame:

data = {'state':['Ohio','Ohio','Ohio','Nevada','Nevada','Nevada'],
        'year':[2000,2001,2002,2001,2002,2003],
        'pop':[1.5,1.7,3.6,2.4,2.9,3.2]}
frame = pd.DataFrame(data)
print(frame)
--------------------------
    state  year  pop
0    Ohio  2000  1.5
1    Ohio  2001  1.7
2    Ohio  2002  3.6
3  Nevada  2001  2.4
4  Nevada  2002  2.9
5  Nevada  2003  3.2

对于大型的DataFrame,head方法将会只选出头部的五行:

print(frame.head())
--------------------
    state  year  pop
0    Ohio  2000  1.5
1    Ohio  2001  1.7
2    Ohio  2002  3.6
3  Nevada  2001  2.4
4  Nevada  2002  2.9

如果指定了列的顺序,DataFrame的列将会按照指定顺序排列:

print(pd.DataFrame(data,columns=['year','state','pop']))
--------------------
   year   state  pop
0  2000    Ohio  1.5
1  2001    Ohio  1.7
2  2002    Ohio  3.6
3  2001  Nevada  2.4
4  2002  Nevada  2.9
5  2003  Nevada  3.2

如果传的列不包含在字典中,将会在结果中出现缺失值:

frame2 = pd.DataFrame(data,columns=['year','state','pop','debt'],
                      index = ['one','two','three','four','five','six'])
print(frame2)
-----------------------------
       year   state  pop debt
one    2000    Ohio  1.5  NaN
two    2001    Ohio  1.7  NaN
three  2002    Ohio  3.6  NaN
four   2001  Nevada  2.4  NaN
five   2002  Nevada  2.9  NaN
six    2003  Nevada  3.2  NaN

DataFrame中的一列,可以按字典型标记或属性那样检索为Series:

print(frame2['state'])
--------------------------
one        Ohio
two        Ohio
three      Ohio
four     Nevada
five     Nevada
six      Nevada
Name: state, dtype: object
print(frame2.year)
--------------------------
one      2000
two      2001
three    2002
four     2001
five     2002
six      2003
Name: year, dtype: int64

frame2[column]对任意列名均有效,但是frame2.column只在列名是有效的python变量名有效。
这里要注意的是,返回的Series与原DataFrame有相同的索引,且Series的name属性也会被合理地设置。
行也可以通过位置或特殊属性loc进行选取:

print(frame2.loc['three'])
--------------------------
year     2002
state    Ohio
pop       3.6
debt      NaN
Name: three, dtype: object

列的索引是可以修改的,例如,空的‘debt’列可以赋值为标量值或值数组:

frame2['debt'] = 16.5
print(frame2)
------------------------------
       year   state  pop  debt
one    2000    Ohio  1.5  16.5
two    2001    Ohio  1.7  16.5
three  2002    Ohio  3.6  16.5
four   2001  Nevada  2.4  16.5
five   2002  Nevada  2.9  16.5
six    2003  Nevada  3.2  16.5
frame2['debt'] = np.arange(6)
print(frame2)
------------------------------
       year   state  pop  debt
one    2000    Ohio  1.5     0
two    2001    Ohio  1.7     1
three  2002    Ohio  3.6     2
four   2001  Nevada  2.4     3
five   2002  Nevada  2.9     4
six    2003  Nevada  3.2     5

将列表或数组赋值给一个列时,值的长度必须和DataFrame的长度相匹配。如果将Series赋值给一列时,Series的索引将会按照DataFrame的索引重新排列,并在空缺的地方填充缺失值:

val = pd.Series([-1.2,-1.5,-1.7],index = ['two','four','five'])
frame2['debt'] = val
print(frame2)
------------------------------
       year   state  pop  debt
one    2000    Ohio  1.5   NaN
two    2001    Ohio  1.7  -1.2
three  2002    Ohio  3.6   NaN
four   2001  Nevada  2.4  -1.5
five   2002  Nevada  2.9  -1.7
six    2003  Nevada  3.2   NaN

如果被赋值的列并不存在,则会生成一个新的列。del关键字可以像在字典中那样对DataFrame删除列。
在del的例子中,我们首先增加一列,这一列是布尔值,判断条件是state列是否为’Ohio’:

frame2['eastern'] = frame2.state == 'Ohio'
print(frame2)
--------------------------------------
       year   state  pop debt  eastern
one    2000    Ohio  1.5  NaN     True
two    2001    Ohio  1.7  NaN     True
three  2002    Ohio  3.6  NaN     True
four   2001  Nevada  2.4  NaN    False
five   2002  Nevada  2.9  NaN    False
six    2003  Nevada  3.2  NaN    False

这里要注意的是frame2.eastern的语法无法创建新的列。
del方法可以用于移除之前新建的列:

del frame2['eastern']
print(frame2.columns)
------------------------------------------------------
Index(['year', 'state', 'pop', 'debt'], dtype='object')

从DataFrame中选取的列是数据的视图,而不是拷贝。因此,对Series的修改会映射到DataFrame中。如果需要复制,则应当显式地使用Series的copy方法。
另一种常用的数据形式是包含字典的嵌套字典,如果嵌套字典被赋值给DataFrame,pandas会将字典的键作为列,将内部字典的键作为行索引:

pop = {'Nevada':{2001:2.4,2002:2.9},
       'Ohio':{2000:1.5,2001:1.7,2002:3.6}}
frame3 = pd.DataFrame(pop)
print(frame3)
------------------
      Nevada  Ohio
2000     NaN   1.5
2001     2.4   1.7
2002     2.9   3.6

也可以使用类似NumPy的语法对DataFrame进行转置操作:

print(frame3.T)
------------------------
        2000  2001  2002
Nevada   NaN   2.4   2.9
Ohio     1.5   1.7   3.6

包含Series的字典也可以用于构造DataFrame:

pdata = {'Ohio':frame3['Ohio'][:-1],
         'Nevada':frame3['Nevada'][:2]}
print(pd.DataFrame(pdata))
------------------
      Ohio  Nevada
2000   1.5     NaN
2001   1.7     2.4

如果DataFrame的索引和列拥有name属性,则这些name属性也会被显示:

frame3.index.name = 'year'
frame3.column.name = 'state'
print(frame3)
-------------------
state  Nevada  Ohio
year               
2000      NaN   1.5
2001      2.4   1.7
2002      2.9   3.6

和Series类似,DataFrame的values属性会将包含在DataFrame中的数据以二维ndarray的形式返回:

print(frame3.values)
---------
[[nan 1.5]
 [2.4 1.7]
 [2.9 3.6]]

如果DataFrame的列是不同的dtypes,则values的dtype会自动选择适合所有列的类型:

print(frame2.values)
-------------------------
[[2000 'Ohio' 1.5 nan]
 [2001 'Ohio' 1.7 -1.2]
 [2002 'Ohio' 3.6 nan]
 [2001 'Nevada' 2.4 -1.5]
 [2002 'Nevada' 2.9 -1.7]
 [2003 'Nevada' 3.2 nan]]

1.3索引对象

pandas中的索引对象是用于存储轴标签和其他元数据的(例如轴名称或标签)。在构造Series或DataFrame时,我们所使用的任意数组或标签序列都可以在内部转换为索引对象:

obj = pd.Series(range(3),index = ['a','b','c'])
index = obj.index
print(index)
--------------------------------------
Index(['a', 'b', 'c'], dtype='object')
print(index[1:])
---------------------------------
Index(['b', 'c'], dtype='object')

索引对象是不可变的,因此用户是无法修改索引对象的。
不变性使得在多种数据结构中分享索引对象更为安全:

labels = pd.Index(np.arange(3))
print(labels)
------------------------------------
Int64Index([0, 1, 2], dtype='int64')
obj2 = pd.Series([1.5,-2.5,0],index = labels)
print(obj2)
--------------
0    1.5
1   -2.5
2    0.0
dtype: float64
print(obj2.index is labels)
----
True

除了类似数组,索引对象也像一个固定大小的集合:

print(frame3.columns)
-----------------------------------------
Index(['Nevada', 'Ohio'], dtype='object')
print('Ohio' in frame3.columns)
----
True
print(2003 in frame3.index)
-----
False

与python集合不同,pandas索引对象可以包含重复标签:

dup_labels = pd.Index(['foo','foo','bar','bar'])
print(dup_labels)
---------------------------------------------------
Index(['foo', 'foo', 'bar', 'bar'], dtype='object')

表1-1:一些索引对象的方法和属性

方法 描述
append 将额外的索引对象粘贴到原索引后,产生一个新的索引
difference 计算两个索引的差集
intersection 计算两个索引的交集
union 计算两个索引的并集
isin 计算表示每一个值是否在传值容器中的布尔数组
delete 将位置i的元素删除,并产生新的索引
drop 根据传参删除指定索引值,并产生新的索引
insert 在位置i插入元素,并产生新的索引
is_monotonic 如果索引序列递增则返回True
is_unique 如果索引序列唯一则返回True
unique 计算索引的唯一值序列
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!