title: 学习 pandas [01]: 数据结构 slug: series-and-dataframe date: 2020-12-27 tags:

  • Pandas
  • Jupyter
  • python category: 数据分析 link: description: type: text

数据结构

pandas的数据类型主要有:

  • Series,类似一维数组
  • DataFrame,类似二维数组

Series

创建Series

1
pd.Series(data, index=index)

data:可以是字典、一维数组、标量

index:索引列表,可以理解为行标签,根据Data的类型而不同。

通过字典创建Series

1
2
3
4
5
6
7
import numpy as np
import pandas as pd

# 通过字典创建,自动采用键值作为索引,若不指定index,则顺序同字典
d = {'b': 1, 'a': 0, 'c': 2}
s = pd.Series(d)
s
b    1
a    0
c    2
dtype: int64
1
2
3
4
# 通过字典创建,自动采用键值作为索引,若指定index(包含键值),则顺序同index
# index中若含有字典中不存在的键值,则Series中对应的值为NaN
s = pd.Series(d, index=['a', 'b', 'c', 'd'])
s
a    0.0
b    1.0
c    2.0
d    NaN
dtype: float64

通过一维数组创建Series

1
2
3
4
5
l = np.random.randn(6)

# 若不指定index,则自动生成数值型索引
s = pd.Series(l)
s
0    0.215224
1    0.803700
2    1.141428
3    0.526450
4    0.577533
5    1.051918
dtype: float64
1
2
3
# 若指定index,则长度必须与数组相同
s = pd.Series(l, index=['a', 'b', 'c', 'd', 'e', 'f'])
s
a    0.215224
b    0.803700
c    1.141428
d    0.526450
e    0.577533
f    1.051918
dtype: float64

通过标量值创建Series

此方法创建出的Series,每行值都相同。

1
2
3
# 必须指定index,Series的长度按照index的长度
s = pd.Series(666, index=['a', 'b', 'c', 'd', 'e', 'f'])
s
a    666
b    666
c    666
d    666
e    666
f    666
dtype: int64

Series具备的方法

如果不在意索引,Series类似于NumPy数组。如果把索引当作键值,则又类似于字典。

Series所具备的方法也与NumPy数组和字典类似。

Series类似数组的方法

  • 切片操作
  • 支持大多数NumPy函数
  • 矢量操作与对齐Series标签:Series之间的操作会自动基于标签对齐数据,不用顾及执行计算操作的Series是否有相同的标签
1
2
3
# 使用numpy的exp()函数作用于每个值
s = pd.Series(l, index=['a', 'b', 'c', 'd', 'e', 'f'])
np.exp(s)
a    1.240139
b    2.233790
c    3.131235
d    1.692912
e    1.781637
f    2.863136
dtype: float64
1
2
3
# 两个具有不同索引标签的Series相加
s1 = pd.Series(1, index=['b', 'c', 'd', 'e', 'g'])
s + s1
a         NaN
b    1.803700
c    2.141428
d    1.526450
e    1.577533
f         NaN
g         NaN
dtype: float64

以上两个不同索引标签的Series相加,操作未对齐索引的Series,结果是所有涉及索引的并集。

Pandas数据结构集成的数据对齐功能,是Pandas区别于大多数标签型数据处理工具的重要特性。

Series类似字典的方法

  • 使用索引标签提取值
    • 引用Series里没有的标签会触发异常
    • get()方法可以提取Series里没有的标签,返回NaN或指定默认值
1
s['d']
0.5264503416237949
1
s.get('g', np.nan)
nan

DataFrame

创建DataFrame

1
pd.DataFrame(data, index=index, columns=columns)

data:可以是一维数组、二维numpy数组、列表、字典、Series字典、Series、DataFrame index:行标签 columns:列标签

通过Series字典创建DtaFrame

1
2
3
4
5
d = {'one': pd.Series([1., 2., 3.], index=['a', 'b', 'c']),
     'two': pd.Series([1., 2., 3., 4.], index=['a', 'b', 'c', 'd'])}
# index、columns分别来自Series字典的索引和键值,index指定行标签顺序,columns指定列标签顺序
df = pd.DataFrame(d, index=['b', 'c', 'd', 'a'], columns=['two', 'one'])
df
twoone
b2.02.0
c3.03.0
d4.0NaN
a1.01.0

通过数组字典创建DataFrame

1
2
3
4
d = {'one': [1., 2., 3., 4.], 'two': [4., 3., 2., 1.]}
#  columns来自数组字典的键值,可指定顺序;index须指定,否则生成自然数索引
df = pd.DataFrame(d, index=['a', 'b', 'c', 'd'], columns=['two', 'one'])
df
twoone
a4.01.0
b3.02.0
c2.03.0
d1.04.0

通过字典列表创建DataFrame

1
2
3
4
d = [{'a': 1, 'b': 2}, {'a': 5, 'b': 10, 'c': 20}]
# columns同样来自字典的键值,可指定顺序;index须指定,否则生成自然数索引
df = pd.DataFrame(d, columns=['a', 'b', 'c'], index=['two', 'one'])
df
abc
two12NaN
one51020.0

通过元组字典创建DataFrame

此方法可以生成多重行标签和列标签。

元组字典的key为元组,value为字典,且该字典的key也是元组。作为key的元组生成多重列标签,value字典中的key生成多重行标签

1
2
3
4
5
6
7
d = {('a', 'b'): {('A', 'B'): 1, ('A', 'C'): 2},
     ('a', 'a'): {('A', 'C'): 3, ('A', 'B'): 4},
     ('a', 'c'): {('A', 'B'): 5, ('A', 'C'): 6},
     ('b', 'a'): {('A', 'C'): 7, ('A', 'B'): 8},
     ('b', 'b'): {('A', 'D'): 9, ('A', 'B'): 10}}
df = pd.DataFrame(d)
df
ab
bacab
AB1.04.05.08.010.0
C2.03.06.07.0NaN
DNaNNaNNaNNaN9.0

提取DataFrame的列

类似于字典,直接用列标签索引。

删除DataFrame的列

两种方法:

  • del df['foo']
  • df.pop['foo']

添加DataFrame的列

插入的列的数据类型可以是:

  • Series,索引不同时以DataFrame为准
  • 原始数组,长度必须与DataFrame一致
  • 标量值,以广播方式填充

插入或生成新列的方法:

  • 类似于字典,直接用列标签索引,默认插入在最后一列
  • insert(位置, 列标签, 数据),可指定列插入位置
  • assign()方法利用现有的列生成新列,此方法返回的是副本,原始DataFrame不会变动

assign()方法举例

1
2
3
d = {'one': [1., 2., 3., 4.], 'two': [4., 3., 2., 1.]}
df = pd.DataFrame(d, index=['a', 'b', 'c', 'd'])
df
onetwo
a1.04.0
b2.03.0
c3.02.0
d4.01.0
1
df.assign(three=df['two']/df['one'])
onetwothree
a1.04.04.000000
b2.03.01.500000
c3.02.00.666667
d4.01.00.250000
1
df.assign(four=lambda x: (x['two']/x['one']))
onetwofour
a1.04.04.000000
b2.03.01.500000
c3.02.00.666667
d4.01.00.250000