Python数据分析05:Pandas的数据结构

CHAPTER 5

Getting Started with pandas


文章目录

  • CHAPTER 5
  • Getting Started with pandas
    • 5.1 pandas的数据结构(Introduction to pandas Data Structures)
      • 5.1.1 Series
      • 5.1.2 数据框(DataFrame)
        • 可以传递给DataFrame的构造器
      • 5.1.3 索引对象(Index Objects)
        • Index的方法和属性


pandas包含数据结构和数据操作工具,通常与NumPySciPy等数值计算工具、statsmodelscikit-learn等分析库以及matplotlib等数据可视化库一起使用。

之后的笔记里,这样导入pandas(也是惯例了):

import pandas as pd

另外可以导入Series和DataFrame,因为这两个经常被用到:

from pandas import Series, DataFrame

5.1 pandas的数据结构(Introduction to pandas Data Structures)

Pandas有三大数据结构,Series、DataFrame以及Panel。

  • Series(一维数据)
  • DataFrame(二维数据)
  • Panel(三维结构数据/面板数据)

注释:对于Panel,会很少使用,通常会使用MultiIndex这种结构解决三维数据表示问题,暂不介绍了就!

5.1.1 Series

这里series我就不翻译成序列了,因为之前的所有笔记里,我都是把sequence翻译成序列的

series是一个像数组一样的一维序列,并伴有一个数组表示label,叫做index。创建一个series的方法也很简单:

>>>obj = pd.Series([4, 7, -5, 3])
>>>obj
0    4
1    7
2   -5
3    3
dtype: int64

可以看到,左边表示index,右边表示对应的value。可以通过value和index属性查看:

>>>obj.values
array([ 4,  7, -5,  3], dtype=int64)
>>>obj.index  # like range(4)
RangeIndex(start=0, stop=4, step=1)

当然我们也可以自己指定index的label:

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

可以用index的label来选择:

>>>obj2['a']
-5
>>>obj2['d'] = 6
>>>obj2[['c', 'a', 'd']]
c    3
a   -5
d    6
dtype: int64

这里[‘c’, ‘a’, ‘d’]其实被当做了索引,尽管这个索引是用string构成的。

使用numpy函数或类似的操作,会保留index-value的关系:

>>>obj2[obj2 > 0]
d    6
b    7
c    3
dtype: int64
>>>obj2 * 2
d    12
b    14
a   -10
c     6
dtype: int64
>>>np.exp(obj2)
d     403.428793
b    1096.633158
a       0.006738
c      20.085537
dtype: float64

另一种看待series的方法,它是一个长度固定,有顺序的dict,从index映射到value。在很多场景下,可以当做dict来用:

>>>'b' in obj2
True
>>>'e' in obj2
False

还可以直接用现有的dict来创建series

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

series中的index其实就是dict中排好序的keys。我们也可以传入一个自己想要的顺序:

>>>states = ['California', 'Ohio', 'Oregon', 'Texas']
>>>obj4 = pd.Series(sdata, index=states)
>>>obj4
California        NaN
Ohio          35000.0
Oregon        16000.0
Texas         71000.0
dtype: float64

顺序是按states里来的,但因为没有找到california,所以是NaN。NaN表示缺失数据,用之后我们提到的话就用missing或NA来指代。pandas中的isnullnotnull函数可以用来检测缺失数据:

>>>pd.isnull(obj4)
California     True
Ohio          False
Oregon        False
Texas         False
dtype: bool
>>>pd.notnull(obj4)
California    False
Ohio           True
Oregon         True
Texas          True
dtype: bool

series也有对应的方法:

>>>obj4.isnull()
California     True
Ohio          False
Oregon        False
Texas         False
dtype: bool

关于缺失数据,在第七章还会讲得更详细一些。

series中一个有用的特色,自动按index label来排序(Data alignment features):

>>>obj3
Ohio      35000
Texas     71000
Oregon    16000
Utah       5000
dtype: int64
>>>obj4
California        NaN
Ohio          35000.0
Oregon        16000.0
Texas         71000.0
dtype: float64
>>>obj3 + obj4
California         NaN
Ohio           70000.0
Oregon         32000.0
Texas         142000.0
Utah               NaN
dtype: float64

这个Data alignment features(数据对齐特色)和数据库中的join相似。

serice自身和它的index都有一个叫name的属性,这个能和其他pandas的函数进行整合:

>>>obj4.name = 'population'
>>>obj4.index.name = 'state'
>>>obj4
state
California        NaN
Ohio          35000.0
Oregon        16000.0
Texas         71000.0
Name: population, dtype: float64

series的index能被直接更改:

>>>obj
0    4
1    7
2   -5
3    3
dtype: int64
>>>obj.index = ['Bob', 'Steve', 'Jeff', 'Ryan']
>>>obj
Bob      4
Steve    7
Jeff    -5
Ryan     3
dtype: int64

5.1.2 数据框(DataFrame)

DataFrame表示一个长方形表格,并包含排好序的列,每一列都可以是不同的数值类型(数字,字符串,布尔值),在Jupyter Notebook中有很美观的显示。DataFrame有行索引和列索引(row index, column index);可以看做是分享所有索引的由series组成的字典。数据是保存在一维以上的区块里的。

(其实我是把dataframe当做excel里的那种表格来用的,这样感觉更直观一些)

构建一个dataframe的方法,用一个dcit,dict里的值是list:

>>>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)
>>>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也会像series一样,自动给数据赋index, 而列则会按顺序排好。

对于一个较大的DataFrame,用head方法会返回前5行(注:这个函数在数据分析中经常使用,用来查看表格里有什么东西,在R中head()函数返回前六行):

>>>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

如果指定一列的话,会自动按列排序:

>>>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'])
>>>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
>>>frame2.columns
Index(['year', 'state', 'pop', 'debt'], dtype='object')

从DataFrame里提取一列的话会返回series格式,可以以属性或是dict一样的形式来提取:

>>>frame2['state']
one        Ohio
two        Ohio
three      Ohio
four     Nevada
five     Nevada
six      Nevada
Name: state, dtype: object
>>>frame2.year  #key
one      2000
two      2001
three    2002
four     2001
five     2002
six      2003
Name: year, dtype: int64

注意:frame2[column]能应对任何列名,但frame2.column的情况下,列名必须是有效的python变量名才行。

返回的series有DataFrame种同样的index,而且name属性也是对应的。

对于行,要用在loc属性里用 位置或名字:

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

列值也能通过赋值改变。比如给debt赋值:

>>>frame2['debt'] = 16.5
>>>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.)
>>>frame2
	    year	state	pop	debt
one	    2000	Ohio	1.5	0.0
two	    2001	Ohio	1.7	1.0
three	2002	Ohio	3.6	2.0
four	2001	Nevada	2.4	3.0
five	2002	Nevada	2.9	4.0
six	    2003	Nevada	3.2	5.0

如果把list或array赋给column的话,长度必须符合DataFrame的长度。如果把一个series赋给DataFrame,会按DataFrame的index来赋值,不够的地方用缺失数据来表示:

>>>val = pd.Series([-1.2, -1.5, -1.7], index=['two', 'four', 'five'])
>>>frame2['debt'] = val
>>>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也能像删除字典关键字一样,删除列:

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

然后用del删除这一列:

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

注意:columns返回的是一个view,而不是新建了一个copy。因此,任何对series的改变,会反映在DataFrame上。除非我们用copy方法来新建一个。

另一种常见的格式是dict中的dict:

>>>pop = {
     'Nevada': {
     2001: 2.4, 2002: 2.9},
>>>       'Ohio': {
     2000: 1.5, 2001: 1.7, 2002: 3.6}}

把上面这种嵌套dcit传给DataFrame,pandas会把外层dcit的key当做列,内层key当做行索引:

>>>frame3 = pd.DataFrame(pop)
>>>frame3
Nevada	Ohio
2001	2.4	1.7
2002	2.9	3.6
2000	NaN	1.5

另外DataFrame也可以向numpy数组一样做转置:

>>>frame3.T
	    2001 2002 2000
Nevada	2.4  2.9  NaN
Ohio	1.7  3.6  1.5

指定index:

>>>pd.DataFrame(pop, index=[2001, 2002, 2003])
		Nevada	Ohio
2001	2.4		1.7
2002	2.9		3.6
2003	NaN		NaN

series组成的dict:

>>>pdata = {
     'Ohio': frame3['Ohio'][:-1],
>>>         'Nevada': frame3['Nevada'][:2]}
>>>pd.DataFrame(pdata)
		Ohio	Nevada
2001	1.7		2.4
2002	3.6		2.9

可以传递给DataFrame的构造器

类型 注释
2D ndarray A matrix of data, passing optional row and column labels
dict of arrays, lists, or tuples Each sequence becomes a column in the DataFrame; all sequences must be the same length
NumPy structured/
record array
Treated as the “dict of arrays” case
dict of Series Each value becomes a column; indexes from each Series are unioned together to form the result’s row index if no explicit index is passed
dict of dicts Each inner dict becomes a column; keys are unioned to form the row index as in the “dict of Series” case
List of dicts or Series Each item becomes a row in the DataFrame; union of dict keys or Series indexes become the DataFrame’s column labels
List of lists or tuples Treated as the “2D ndarray” case
Another DataFrame The DataFrame’s indexes are used unless diferent ones are passed
NumPy MaskedArray Like the “2D ndarray” case except masked values become NA/missing in the DataFrame result

如果DataFrame的index和column有自己的name属性,也会被显示:

>>>frame3.index.name = 'year'; frame3.columns.name = 'state'
>>>frame3
state	Nevada	Ohio
year		
2001	2.4		1.7
2002	2.9		3.6
2000	NaN		1.5

values属性会返回二维数组:

>>>frame3.values
array([[2.4, 1.7],
       [2.9, 3.6],
       [nan, 1.5]])

如果column有不同的类型,dtype会适应所有的列:

>>>frame2.values
array([[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]], dtype=object)

5.1.3 索引对象(Index Objects)

pandas的Index Objects (索引对象)负责保存axis labels和其他一些数据(比如axis name或names)。一个数组或其他一个序列标签,只要被用来做构建series或DataFrame,就会被自动转变为index:

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

index object是不可更改的:

>>>index[1] = 'd' 
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-129-a452e55ce13b> in <module>
----> 1 index[1] = 'd'

H:\Anaconda3\lib\site-packages\pandas\core\indexes\base.py in __setitem__(self, key, value)
   4258 
   4259     def __setitem__(self, key, value):
-> 4260         raise TypeError("Index does not support mutable operations")
   4261 
   4262     def __getitem__(self, key):

TypeError: Index does not support mutable operations

正因为不可修改,所以data structure中分享index object是很安全的:

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

index除了像数组,还能像大小一定的set:

>>>frame3
state	Nevada	Ohio
year		
2001	2.4		1.7
2002	2.9		3.6
2000	NaN		1.5
>>>frame3.columns
Index(['Nevada', 'Ohio'], dtype='object', name='state')
>>>'Ohio' in frame3.columns
True
>>>2003 in frame3.index
False

与python里的set不同,pandas的index可以有重复的labels:

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

在这种重复的标签中选择的话,会选中所有相同的标签。

Index的方法和属性

方法 描述
append 连接新的index对象,产生新的index对象
difference 计算差集,并得到一个index
intersection 计算交集
union 计算并集
isin 计算一个指示各值是否都包含在参数集合的布尔型数组
delete 删除索引i处的元素,并的新的index
drop 删除传入的值,并得到新的index
insert 当元素插入到索引i处,并得到新的index
is_monotonic 当个元素大于等于一个元素时,返回True
is_unique 当index没有重复值时,返回True
unique 计算index中惟一值的数组

参考资料:

  • 利用Python进行数据分析学习笔记(有惊喜^_^
  • 书籍:《Python for Data Analysis》

你可能感兴趣的:(利用Python进行数据分析,python,数据分析,数据结构)