pandas入门

写在前面的话

在做天文数据处理的过程中,基本上是和表格数据打交道,因此在处理天文数据的过程中pandas就是自己首选。利用pandas可以很方便的提取出自己想要的行或列的数据,方便自己后面做统计分析。因此,写一篇pandas入门的文章记录一下自己学习pandas的总结。

推荐另外一篇pandas入门文档:10 Minutes to pandas

pandas的功能

  1. 具备按轴自动或显式数据对齐功能的数据结构。这可以防止许多由于数据未对齐以及来自不同数据源(索引方式不同)的数据而导致的常见错误。
  2. 集成时间序列功能。
  3. 既能处理时间序列数据也能处理非时间序列数据的数据结构。
  4. 数学运算和约简(比如对某个轴求和)可以根据不同的元数据(轴号)执行。
  5. 灵活处理缺失数据。
  6. 合并及其他出现在常见数据库(例如基于SQL的)中的关系型运算。

pandas引入约定

import pandas as pd
from pandas import Series,DataFrame

pandas数据结构介绍

要使用pandas,必须先要熟悉它的两个主要数据结构:SeriesData Frame

Series

Series是一种类似于一维数组的对象,它由一组数据和一组与之相关的数据标签(索引)组成。

由一组数据生产简单的Series
a = [1,3,'hello',4.5]
b =pd.Series(a)
print(b)
0        1
1        3
2    hello
3      4.5
dtype: object

Series的表现形式为:索引在左边,值在右边。由于没有为数据指定索引,默认自动创建一个0到n-1(n为数据的长度)的整数型索引。可以通过Series的values和index属性获取其数组表示形式和索引对象:

b.values
array([1, 3, 'hello', 4.6], dtype=object)
b.index  #like range(4)
RangeIndex(start=0, stop=4, step=1)

通过索引可以获取对应的值:

b[2]
'hello'
b[1:3]
1        3
2    hello
dtype: object
b[[1,2]]
1        3
2    hello
dtype: object

自定义索引:

a = [1,3,'hello',4.5]
c = pd.Series(a,index=[c,d,m,n])
print(c)
c        1
d        3
m    hello
n      4.6
dtype: object
c['d']
3
c[['m','n']]
m    hello
n      4.6
dtype: object

使用Numpy函数或者Numpy的运算,都会保留索引值的链接:

obj =pd.Series([1,5,7,3,2,-3])
print(obj)
0    1
1    5
2    7
3    3
4    2
5   -3
dtype: int64
obj[obj<3]
0    1
4    2
5   -3
dtype: int64
obj + 1
0    2
1    6
2    8
3    4
4    3
5   -2
dtype: int64

可以将Series看成是一个定长的有序字典,因为它是索引值到数据值的一个映射。

print(c)
c        1
d        3
m    hello
n      4.6
dtype: object
'm' in c
True
's' in c
False

如果数据被存放在一个Python字典中,可以直接通过这个字典来创建Series。

data = {'Tom':25,'Jerry':23,'Allon':26,'xiaoming':7}
sdata = Series(data)
sdata
Tom         25
Jerry       23
Allon       26
xiaoming     7
dtype: int64

如果只传入一个字典,则结果Series中的索引就是原字典中的键(Key)。当然你也可以传入排好序的字典的键来改变顺序。

name = ['Jerry','xiaoming','Tom','Bob']
obj1 = Series(data,index=name)
print(obj1)
Jerry       23.0
xiaoming     7.0
Tom         25.0
Bob          NaN
dtype: float64

由于'Bob'所对应的值找不到,所以就显示NAN(not a number),在pandas中NAN用于表示缺失或者NA值。由于'Allon'不在name中,所以它被从结果中除去。
pandas中的isnullnotnull函数可用于检查缺失的数据:

pd.isnull(obj1)
Jerry       False
xiaoming    False
Tom         False
Bob          True
dtype: bool
#Series也有类似的用法,是指已经导入Series函数
obj1.isnull()
Jerry       False
xiaoming    False
Tom         False
Bob          True
dtype: bool

Series会根据运算的索引自动对齐数据(类似join操作):

obj2 = Series({'a':4,'d':6,'k':8,'f':7})
obj3 = Series({'d':1,'f':3,'a':6,'n':5})
obj2 + obj3
a    10.0
d     7.0
f    10.0
k     NaN
n     NaN
dtype: float64

Series的name属性,该属性与pandas其它关键功能关系密切:

obj1
Jerry       23.0
xiaoming     7.0
Tom         25.0
Bob          NaN
dtype: float64
obj1.name = 'population'
obj1.index.name = 'name'
print(obj1)
name
Jerry       23.0
xiaoming     7.0
Tom         25.0
Bob          NaN
Name: population, dtype: float64

Series的索引值可以通过赋值方式就地修改:

obj2
a    4
d    6
k    8
f    7
dtype: int64
obj2.index = ['e','f','h','m']
obj2
e    4
f    6
h    8
m    7
dtype: int64

DataFrame

DataFrame是一个表格型的数据结构,它含有一组有序的列,每列可以是不同的值类型(数值、字符串、布尔值等)。DataFrame既有行索引也有列索引。
建DataFrame的办法有很多,最常用的一种是直接传入一个由等长列表或Numpy数组组成的字典:

data1 = {'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(data1)
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的方法:

f = [8,5,3,7]
m = [15,75,34,52]
fm = pd.DataFrame([f,m])
fm
    0   1   2   3
0   8   5   3   7
1   15  75  34  52

没有索引(行or列),DataFrame会自动加上(跟Series一样)。
对于特别大的DataFrame,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

如果指定列序列,则DataFrame的列就会按照指定的顺序排列:

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

通过类似字典标记的方式或属性的方式,可以将DataFrame的某一列获取为一个Series:

frame['pop']
0    1.5
1    1.7
2    3.6
3    2.4
4    2.9
5    3.2
Name: pop, dtype: float64
frame.year
0    2000
1    2001
2    2002
3    2001
4    2002
5    2003
Name: year, dtype: int64

提示:返回的Series拥有原DataFrame相同的索引,而且name属性也被相应的设置好了。

行也可以通过位置或者名称进行获取,比如用loc属性

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
frame.loc[0]
state    Ohio
year     2000
pop       1.5
Name: 0, dtype: object

列可以通过赋值的方式进行修改:

frame['pop'] = 2.0
frame
    state   year    pop
0   Ohio    2000    2.0
1   Ohio    2001    2.0
2   Ohio    2002    2.0
3   Nevada  2001    2.0
4   Nevada  2002    2.0
5   Nevada  2003    2.0

将列表或数组赋值给某个列时,其长度必须跟DataFrame的长度相匹配。如果赋值的是一个Series,就会精确匹配DataFrame的索引,所有的空位都将被填上缺失值。

#此例是直接添加某一列,当pop列本身存在时,就是赋值。
frame['pop'] = np.arange(6.)
frame
    state   year    pop
0   Ohio    2000    0.0
1   Ohio    2001    1.0
2   Ohio    2002    2.0
3   Nevada  2001    3.0
4   Nevada  2002    4.0
5   Nevada  2003    5.0
#Series
val = pd.Series([1.2,4.3,5.7], index=[0,3,5])
frame['add'] = val
frame
    state   year    pop add
0   Ohio    2000    0.0 1.2
1   Ohio    2001    1.0 NaN
2   Ohio    2002    2.0 NaN
3   Nevada  2001    3.0 4.3
4   Nevada  2002    4.0 NaN
5   Nevada  2003    5.0 5.7

使用del函数可以删除某一列:

del frame['pop']
frame
    state   year
0   Ohio    2000
1   Ohio    2001
2   Ohio    2002
3   Nevada  2001
4   Nevada  2002
5   Nevada  2003

另一种常见的数据形式是嵌套字典:

data2 = {'Nevada':{2001:2.4, 2002:2.9},
        'Ohio':{2000:1.5, 2001:1.7, 2002:3.6}}
frame1 = pd.DataFrame(data2)
frame1
    Nevada  Ohio
2000    NaN 1.5
2001    2.4 1.7
2002    2.9 3.6

Tips:外层字典的键作为列,内层字典的键作为行索引。

对DataFrame进行转值:

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

设置DataFrame的index和columns的name属性:

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

可以输入给DataFrame构造器的数据类型:

Screen Shot 2019-06-13 at 16.22.31.png

pandas基本功能

本节介绍处理Series和DataFrame中的数据的基本手段,更详细的pandas库介绍可以看官网文档User_Guide

重新索引

pandas中的reindex是创建一个新的对象,使得数据符合新的索引。如果某个索引值当前不存在,则填入确实值。

obj4 = pd.Series([4.5,7.2,-5.3,3.6], index=['d','b','a','c'])
obj4
d    4.5
b    7.2
a   -5.3
c    3.6
dtype: float64
obj5 = obj4.reindex(['a','b','c','d','e'])
obj5
a   -5.3
b    7.2
c    3.6
d    4.5
e    NaN
dtype: float64
reindex函数的参数
参数 说明
index 用作索引的新序列
method 插值(填充)方式,ffill or pad 向前填充值;bfill or backfill 向后填充值
fill_value 引入缺失值时使用的替代值
limit 向前或向后填充时的最大填充量
tolerance 向前或向后填充时,填充不准确匹配项的最大间距(绝对距离)
level 在Multilndex的指定级别上匹配简单索引,否则选取其子集
copy 默认为True,无论如何都复制;如果为False,则新旧相等就不复制

向前填充:

obj6 = pd.Series(['blue', 'yellow', 'orange'],index=[0,2,4])
obj6
0      blue
2    yellow
4    orange
dtype: object
obj6.reindex(range(6),method='ffill')
0      blue
1      blue
2    yellow
3    yellow
4    orange
5    orange
dtype: object

列可以用columns关键字重新索引:

frame2 = pd.DataFrame(np.arange(9).reshape((3,3),),
                     index=['a', 'c', 'd'],
                     columns=['Ohio', 'Texas', 'California'])
frame2
    Ohio    Texas   California
a   0       1       2
c   3       4       5
d   6       7       8
states = ['Ohio', 'Utah', 'California']
frame2.reindex(columns=states)
    Ohio    Utah    California
a   0       NaN     2
c   3       NaN     5
d   6       NaN     8

丢弃指定轴上的项drop函数

obj6.drop(2)
0      blue
4    orange
dtype: object
#axis=0 or axis='rows'传递为行(默认);axis=1 or axis='columns'传递为列
frame2.drop('Ohio', axis=1)
    Texas   California
a   1       2
c   4       5
d   7       8
#当drop函数中的参数设置为inplace=True时,就地修改对象,不会返回新的对象。必须要小心使用inplace,它会销毁所有被删除的数据

索引、选取和过滤

Series索引的工作方式类似于Numpy数组的索引,只不过Series的索引值不只是整数。

obj5
a   -5.3
b    7.2
c    3.6
d    4.5
e    NaN
dtype: float64
#利用标签切片运算与普通的Python的切片不同,其末端是包含的
obj5['a':'c']
a   -5.3
b    7.2
c    3.6
dtype: float64
#不用标签索切片时,与Python的切片相同
obj5[:3]
a   -5.3
b    7.2
c    3.6
dtype: float64

用一个值或序列对DataFrame进行索引其实就是获取一个或多个列:

frame
    state   year    pop add
0   Ohio    2000    0.0 1.2
1   Ohio    2001    1.0 NaN
2   Ohio    2002    2.0 NaN
3   Nevada  2001    3.0 4.3
4   Nevada  2002    4.0 NaN
5   Nevada  2003    5.0 5.7
frame[['state', 'pop']]
    state   pop
0   Ohio    0.0
1   Ohio    1.0
2   Ohio    2.0
3   Nevada  3.0
4   Nevada  4.0
5   Nevada  5.0
frame[1:4]
    state   year    pop add
1   Ohio    2001    1.0 NaN
2   Ohio    2002    2.0 NaN
3   Nevada  2001    3.0 4.3
frame[frame['pop']>3]
    state   year    pop add
4   Nevada  2002    4.0 NaN
5   Nevada  2003    5.0 5.7

用loc和iloc进行选

对于DataFrame的行的标签索引,可以使用特殊的标签运算符轴标签loc和整数索引iloc。

frame.loc[3,['state', 'pop']]
state    Nevada
pop           3
Name: 3, dtype: object
#iloc可以这样理解:不管有没有设置新的行或列索引,默认的索引都是存在的,而iloc就是提取默认的索引值。
frame.iloc[3,[0,2]]
state    Nevada
pop           3
Name: 3, dtype: object

DataFrame数据选取与整合总结

类型 说明
df[val] 选取单列数据
df.loc[val] 通过标签,选取DataFrame的单行数据
df.loc[:,val] 通过标签,选取单列数据
df.loc[,val1, val2] 通过标签,同时选取行和列对应的数据
df.iloc[where] 通过整数位置,选取单个行数据
df.oloc[:, where] 通过整数位置,选取单个列数据
df.iloc[where_i, where_j] 通过整数位置,同时选取行和列对应的数据
df.at[label_i, label_j] 通过行标签和列标签,选取对应的数据
df.iat[i,j] 通过行和列的位置(整数),选取对应的数据
reindex 通过标签选取行或列
get_value,set_value 通过行和列标签选取数据

算术运算和数据对齐

pandas最重要的一个功能是:对不同索引的对象进行算术运算,当数据相加时,如果存在不同索引,则结果的索引是所有数据索引的并集。

s1 = pd.Series([2,5,7,1], index=['a', 'c', 'd', 'e'])
s2 = pd.Series([1,7,9,3,4], index=['a', 'c', 'e', 'f', 'g'])
s1
a    2
c    5
d    7
e    1
dtype: int64
s2
a    1
c    7
e    9
f    3
g    4
dtype: int64
#自动的数据对齐操作在不重叠的索引处引入了NA值,对于DataFrame会同时发生在行和列上
s1 + s2
a     3.0
c    12.0
d     NaN
e    10.0
f     NaN
g     NaN
dtype: float64

在算术方法中填充值

在对不同索引的对象进行算术运算时,我们可能希望当一个对象中某个轴标签在另一个对象中找不到时填充一个特殊值(比如0)。此时可以使用算术方法在fill_value传入参数0.

df1 = pd.DataFrame(np.arange(12.).reshape((3,4)),
                  columns=list('abcd'))
df2 = pd.DataFrame(np.arange(20.).reshape((4,5)),
                  columns=list('abcde'))
df1
    a   b   c   d
0   0.0 1.0 2.0 3.0
1   4.0 5.0 6.0 7.0
2   8.0 9.0 10.011.0
df2
    a   b   c   d   e
0   0.0 1.0 2.0 3.0 4.0
1   5.0 6.0 7.0 8.0 9.0
2   10.011.012.013.014.0
3   15.016.017.018.019.0
df1 + df2
    a   b   c   d   e
0   0.0 2.0 4.0 6.0 NaN
1   9.0 11.013.015.0NaN
2   18.020.022.024.0NaN
3   NaN NaN NaN NaN NaN
#填充值0
df1.add(df2,fill_value=0)
    a       b       c       d       e
0   0.0     2.0     4.0     6.0     4.0
1   9.0     11.0    13.0    15.0    9.0
2   18.0    20.0    22.0    24.0    14.0
3   15.0    16.0    17.0    18.0    19.0

Series和DataFrame算术方法

每个算术方法都有一个副本,以字母r开头,它会翻转参数。两个语句等价。

方法 说明
add +加
sub, rsub -减
div, rdiv /除
floordiv, rfloordiv //底除
mul, rmul *乘
pow, rpow **指数

DataFrame和Series之间的运算

arr = np.arange(12).reshape((3,4))
arr
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
arr[0]
array([0, 1, 2, 3])
#从arr减去arr[0],每一行都会执行这个操作。这叫做广播(broadcasting)
arr - arr[0]
array([[0, 0, 0, 0],
       [4, 4, 4, 4],
       [8, 8, 8, 8]])
#DataFrame和Series之间的运算差不多也是如此
frame3 = pd.DataFrame(np.arange(12).reshape((4,3)),
                     columns=list('abc'),
                     index=list('EMNF'))
frame3
    a   b   c
E   0   1   2
M   3   4   5
N   6   7   8
F   9   10  11
s3 = frame3.iloc[0]
s3
a    0
b    1
c    2
Name: E, dtype: int64
frame3 - s3
    a   b   c
E   0   0   0
M   3   3   3
N   6   6   6
F   9   9   9

如果希望在列上传播,则必须使用算术运算方法。

s4 = frame3['a']
s4
E    0
M    3
N    6
F    9
Name: a, dtype: int64
frame3.sub(s4,axis='index')
    a   b   c
E   0   1   2
M   0   1   2
N   0   1   2
F   0   1   2

函数应用和映射

Numpy的函数也可以用于操作pandas对象:

np.add(frame3,2)
    a   b   c
E   2   3   4
M   5   6   7
N   8   9   10
F   11  12  13

另一个常见的操作是,将函数应用到各列或各行所形成的一维数组上。DataFrame的applay方法即可实现此功能。

frame3
    a   b   c
E   0   1   2
M   3   4   5
N   6   7   8
F   9   10  11
f = lambda x: x.max() - x.min()
frame3.apply(f)
a    9
b    9
c    9
dtype: int64

def f(x):
    return pd.Series([x.min(), x.max()], index=['min', 'max'])
frame3.apply(f, axis='columns')
    min max
E   0   2
M   3   5
N   6   8
F   9   11

frame4 = pd.DataFrame(np.random.randn(4,3),
                     columns=list('abc'),
                     index=list('DEFG'))
frame4
    a           b           c
D   0.279946    0.697885    -0.159838
E   -0.890032   0.480782    1.053987
F   -0.734350   -0.869877   0.439226
G   1.591106    0.822776    0.350413
#使用applymap函数得到frame4中各个浮点值的格式化字符串
f = lambda x: '%.2f' %x
frame4.applymap(f)
    a       b       c
D   0.28    0.70    -0.16
E   -0.89   0.48    1.05
F   -0.73   -0.87   0.44
G   1.59    0.82    0.35

结语:有关pandas的入门介绍就写到此,上面的笔记都是自己看《利用Python进行数据分析》第五章节的记录,绝大部分是书中的例题,也有一小部分是自己的添加的。

参考书籍:《利用Python进行数据分析》

2019-06-13

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

推荐阅读更多精彩内容