本文介绍pandas的基本数据类型,要熟练使用pandas,需要熟悉它的两种主要数据结构:Series和DataFrame
1.Series
Series 形如于一维矩阵的对象,通常用来存储一列数值,其包含数值列(与numpy数据格式相似)和标签列(与数值列相对应,称之为index列)
1.1 Series生成
最简单的Series可以由一个数值list生成
代码语言:javascript复制import pandas as pd
from pandas import Series, DataFrame
import numpy as np
obj = pd.Series([4, 7, -5, 3])
obj
代码语言:javascript复制0 4
1 7
2 -5
3 3
dtype: int64
输出结果中,左边列代表标签列(index),后边列则是我们输入的数值。因为没有在生成Series的时候设置index列,所以pandas会创建由0到N-1的默认索引(N为数据长度)
此时可以分别values和index属性,如下:
代码语言:javascript复制obj.values
代码语言:javascript复制array([ 4, 7, -5, 3], dtype=int64)
代码语言:javascript复制obj.index # like range(4)
代码语言:javascript复制RangeIndex(start=0, stop=4, step=1)
当默认index无法满足使用时,我们生成Series时可以同时设置index列,比如:
代码语言:javascript复制obj2 = pd.Series([4, 7, -5, 3], index=['b', 'b', 'a', 'c'])
obj2
代码语言:javascript复制b 4
b 7
a -5
c 3
dtype: int64
代码语言:javascript复制obj2.index
代码语言:javascript复制Index(['b', 'b', 'a', 'c'], dtype='object')
和numpy数组相比,Series可以通过index直接取某个数,或者一组数的集合
代码语言:javascript复制obj2['a']
代码语言:javascript复制-5
代码语言:javascript复制obj2[['a', 'b', 'c']]
代码语言:javascript复制a -5
b 4
b 7
c 3
dtype: int64
也可以直接修改/增加相应的值,类似于dict
代码语言:javascript复制obj2['d'] = 6
obj2['e'] = 10
obj2
代码语言:javascript复制b 4
b 7
a -5
c 3
d 6
e 10
dtype: int64
1.2 Series运算
可以直接使用numpy的方法,或者和numpy类似的运算操作对Series对象进行运算
代码语言:javascript复制# 1.布尔矩阵操作
obj2[obj2 > 0]
代码语言:javascript复制b 4
b 7
c 3
d 6
e 10
dtype: int64
代码语言:javascript复制# 2.乘一个标量
obj2 * 2
代码语言:javascript复制b 8
b 14
a -10
c 6
d 12
e 20
dtype: int64
代码语言:javascript复制# 3.numpy函数直接运算
np.exp(obj2)
代码语言:javascript复制b 54.598150
b 1096.633158
a 0.006738
c 20.085537
d 403.428793
e 22026.465795
dtype: float64
1.3 Series与dict关系
由上述例子可以感受到,Series与dict有很多类似之处
通俗的理解,Series可以看成是固定长度的有序字典,并且index对values有映射关系,多数情况下可以直接当成字典使用,例如
代码语言:javascript复制'b' in obj2
代码语言:javascript复制True
代码语言:javascript复制'e' in obj2
代码语言:javascript复制True
也可通过dict直接生成Series
代码语言:javascript复制sdata = {
'Ohio': 35000,
'Texas': 71000,
'Oregon': 16000,
'Utah': 5000
}
obj3 = pd.Series(sdata)
obj3
代码语言:javascript复制Ohio 35000
Texas 71000
Oregon 16000
Utah 5000
dtype: int64
同样,这种生成方式也可单独设置index,因为dict中已经有key和value的对应关系,此时如果设置的index列与dict中的keys有冲突,以index为准,例如
代码语言:javascript复制states = ['California', 'Ohio', 'Oregon', 'Texas']
obj4 = pd.Series(sdata, index=states)
obj4
代码语言:javascript复制California NaN
Ohio 35000.0
Oregon 16000.0
Texas 71000.0
dtype: float64
上述例子中,"California"为index中新出现的值,且不在原始dict中,因此对应的value为NaN。而"Utah"不在index中,所以被排除
1.4 Series的name属性
简单地讲,name属性相当于给整个Series或者Series的index附加一个命名,方便展示,例如:
代码语言:javascript复制obj4.name = 'population'
obj4.index.name = 'state'
obj4
代码语言:javascript复制state
California NaN
Ohio 35000.0
Oregon 16000.0
Texas 71000.0
Name: population, dtype: float64
Series做为pandas最基础的数据结构,它的基础介绍和基本使用方法介绍完了,让我们回头开头,Series代表着1列数据,如果把它扩展到N列,那么
没错,就是接下来要介绍的DataFrame
2.DataFrame
DataFrame为pandas中最重要的数据结构,它的格式等同于我们要处理的矩形表格:拥有多列,每列可以有不同类型的数据,拥有列名,行、列索引等...
DataFrame可以认为是Series的扩展或者是一系列Series的组合,且看用法
2.1 DataFrame生成
DataFrame的生成方式有很多种,最通常的是通过等长的list组成的的dict
代码语言:javascript复制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可能会很大,而你只是想看看基础的数据格式,此时可用head()来观察前几行
代码语言:javascript复制frame.head(10)
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 |
有head(), 也有tail()
代码语言:javascript复制frame.tail(3)
state | year | pop | |
---|---|---|---|
3 | Nevada | 2001 | 2.4 |
4 | Nevada | 2002 | 2.9 |
5 | Nevada | 2003 | 3.2 |
如果想要columns按顺序排列,对columns赋值即可
代码语言:javascript复制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 |
如果columns中传入的值并不在dict中,那么会以缺失值的形式呈现,这同理于Series的index赋值
代码语言:javascript复制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 |
另外,DataFrame中的index和columns属性可以查看相应内容
代码语言:javascript复制frame2.columns
代码语言:javascript复制Index(['year', 'state', 'pop', 'debt'], dtype='object')
代码语言:javascript复制frame2.index
代码语言:javascript复制Index(['one', 'two', 'three', 'four', 'five', 'six'], dtype='object')
2.2 DataFrame取数
DataFrame作为二维格式,取数会比较花哨一点
代码语言:javascript复制# 1.取某一列的所有值,类似于字典取数
frame2['state']
代码语言:javascript复制one Ohio
two Ohio
three Ohio
four Nevada
five Nevada
six Nevada
Name: state, dtype: object
代码语言:javascript复制# 2.取某一列的所有值,还可以类似于调用类的属性,由于不常用,在此不推荐使用,了解即可
frame2.state # 不推荐
代码语言:javascript复制one Ohio
two Ohio
three Ohio
four Nevada
five Nevada
six Nevada
Name: state, dtype: object
代码语言:javascript复制# 3.取某一行的所有值,已知行标签的情况下
frame2.loc['three']
代码语言:javascript复制year 2002
state Ohio
pop 3.6
debt NaN
Name: three, dtype: object
代码语言:javascript复制# 4.取某一行的所有值,已知第几行的情况下
frame2.iloc[4]
代码语言:javascript复制year 2002
state Nevada
pop 2.9
debt NaN
Name: five, dtype: object
2.3 DataFrame运算
DataFrame运算时,对于某一列的数学运算和Series方法相同,二维运算中比较重要的有转置,例如:
代码语言:javascript复制# pd的转置,可以使用类似矩阵转置的方法
frame2.T
one | two | three | four | five | six | |
---|---|---|---|---|---|---|
year | 2000 | 2001 | 2002 | 2001 | 2002 | 2003 |
state | Ohio | Ohio | Ohio | Nevada | Nevada | Nevada |
pop | 1.5 | 1.7 | 3.6 | 2.4 | 2.9 | 3.2 |
debt | NaN | NaN | NaN | NaN | NaN | NaN |