Pandas的数据结构

Pandas核心的数据结构有两种,表示一维的series和二维的dataframe,二者可以分别看做是在numpy一维数组和二维数组的基础上增加了相应的标签信息。numpy中关于数组的用法基本可以直接应用到这两个数据结构,包括数据创建、切片访问、通函数、广播机制等

Series

它是一种类似于一维数组的对象,是由一组数据(各种NumPy数据类型)以及一组与之相关的数据标签(即索引)组成。仅由一组数据也可产生简单的Series对象。

img

Series支持的数据类型包括:

  • Python字典
  • ndarray
  • 标量

如何创建Series?

s1 = pd.Series(data=np.random.randn(5), index=['a', 'b', 'c', 'd', 'e'])## ndarray
d = {'a': 1, 'b': 2, 'c': 3}
s2 = pd.Series(data=d) ## Python字典
s3 = pd.Series(data=d, index=['a', 'm', 'n']) ## Python字典
s4 = pd.Series(data=5., index=['a', 'b', 'c', 'd', 'e']) ## 标量

index为标签列表

Series的属性操作

理解Series的属性,比如ndim/shape/dtypes/size,分别表示了数据的维数、形状、数据类型和元素个数:

s1 = pd.Series(data=np.random.randn(5), index=['a', 'b', 'c', 'd', 'e'])
print(s1)

输出的结果为:

img

print(s1.ndim) ## 1
print(s1.shape) ## (5,)
print(s1.dtypes) ## float64
print(s1.dtype)## float64
"""
由于pandas允许数据类型是异构的,各列之间可能含有多种不同的数据类型,所以dtype取其复数形式dtypes。
与此同时,series因为只有一列,所以数据类型自然也就只有一种,pandas为了兼容二者,series的数据类型属性既可以用dtype也可以用dtypes获取;
而dataframe则只能用dtypes。
"""
print(s1.size)## 5

d = {'a': 1, 'b': 2, 'c': 3}
s2 = pd.Series(data=d)

print(s1.array)
"""
<PandasArray>
[-0.42215731012740565,   -1.302176998745536,   0.8425921792645086,
  0.07607689395042025,    2.845175479227247]
Length: 5, dtype: float64
"""
print(s1.to_numpy())  # [-0.42215731 -1.302177    0.84259218  0.07607689  2.84517548]
print(s1.index)  # Index(['a', 'b', 'c', 'd', 'e'], dtype='object')
print(s1[0])  # -0.42215731012740565
print(s1['a'])  # -0.42215731012740565
print('a' in s1)  # True
print(s1.get('f'), np.nan)  # None nan
print(s1 + s1)
"""
a   -0.844315
b   -2.604354
c    1.685184
d    0.152154
e    5.690351
dtype: float64
"""
print(s1 + s2)
"""
a    0.577843
b    0.697823
c    3.842592
d         NaN
e         NaN
dtype: float64
"""

DataFrame

DataFrame是Pandas中的一个表格型的数据结构,包含有一组有序的列,每列可以是不同的值类型(数值、字符串、布尔型等),DataFrame即有行索引也有列索引,可以被看做是由Series组成的字典。

img

类似于 Excel 、SQL 表,或 Series 对象构成的字典。DataFrame 是最常用的 Pandas 对象,与 Series 一样,DataFrame支持多种类型的输入数据:

如何创建DataFrame?

用 Series 字典或字典生成 DataFrame

可以使用多个Serics生成DataFrame:

img

s1 = pd.Series(data=np.random.randn(5), index=['a', 'b', 'c', 'd', 'e'])
s2 = pd.Series(data={'a': 1, 'b': 2, 'c': 3})

sd = {'one': s1, 'two': s2}
d1 = pd.DataFrame(data=sd)

print(d1)

"""
        one  two
a -2.210606  1.0
b -0.260349  2.0
c -0.158748  3.0
d  0.047268  NaN
e  1.588751  NaN
"""
d2 = pd.DataFrame(sd, index=['d', 'b'])
print(d2)
"""
        one  two
d  0.047268  NaN
b -0.260349  2.0
"""
d3 = pd.DataFrame(sd, columns=['two', 'three'])
print(d3)
"""
   two three
a    1   NaN
b    2   NaN
c    3   NaN
"""

用多维数组字典、列表字典生成 DataFrame

sd = {'one': [1, 2, 3, 4], 'two': [5, 6, 7, 8]}
d1 = pd.DataFrame(data=sd)

print(d1)

"""
   one  two
0    1    5
1    2    6
2    3    7
3    4    8
"""
d2 = pd.DataFrame(sd, index=['0', '2', '1', '3'])
print(d2)
"""
   one  two
0    1    5
2    2    6
1    3    7
3    4    8
"""
d3 = pd.DataFrame(sd, columns=['two', 'three'])
print(d3)
"""
   two three
0    5   NaN
1    6   NaN
2    7   NaN
3    8   NaN
"""

用结构多维数组或记录多维数组生成 DataFrame

data = np.zeros((2,), dtype=[('A', 'i4'), ('B', 'f4'), ('C', 'a10')])
data[:] = [(1, 1., 'test1'), (2, 2., 'test2')]
d1 = pd.DataFrame(data)
print(d2)
"""
  A    B         C
0  1  1.0  b'test1'
1  2  2.0  b'test2'
"""
d2 = pd.DataFrame(data, index=['first', 'second'])
print(d2)
"""
        A    B         C
first   1  1.0  b'test1'
second  2  2.0  b'test2'
"""
d3 = pd.DataFrame(data, columns=['C', 'A', 'B'])
print(d3)
"""
          C  A    B
0  b'test1'  1  1.0
1  b'test2'  2  2.0
"""

用列表字典生成 DataFrame

sd = [{'a': 1, 'b': 2}, {'a': 5, 'b': 10, 'c': 20}]
d1 = pd.DataFrame(data=sd)

print(d1)

"""
   a   b     c
0  1   2   NaN
1  5  10  20.0
"""
d2 = pd.DataFrame(sd, index=['first', 'second'])
print(d2)
"""
        a   b     c
first   1   2   NaN
second  5  10  20.0
"""
d3 = pd.DataFrame(sd, columns=['a', 'b'])
print(d3)
"""
   a   b
0  1   2
1  5  10
"""

用元组字典生成 DataFrame

d1 = pd.DataFrame({('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}})

print(d1)

"""
       a              b      
       b    a    c    a     b
A B  1.0  4.0  5.0  8.0  10.0
  C  2.0  3.0  6.0  7.0   NaN
  D  NaN  NaN  NaN  NaN   9.0
"""

备选构建器

DataFrame.from_dict

特别注意的是 orient 参数,默认为 columns,把 orient 参数设置为 'index', 即可把字典的键作为行标签。

d1 = pd.DataFrame.from_dict(dict([('A', [1, 2, 3]), ('B', [4, 5, 6])]))

print(d1)

"""
   A  B
0  1  4
1  2  5
2  3  6
"""
d2 = pd.DataFrame.from_dict(dict([('A', [1, 2, 3]), ('B', [4, 5, 6])]), orient='index', columns=['a', 'b', 'c'])
print(d2)
"""
   a  b  c
A  1  2  3
B  4  5  6
"""

DataFrame.from_records

          A    B
C               
b'test1'  1  1.0
b'test2'  2  2.0

DataFrame的属性操作

提取、设置、删除列

  • DataFrame 就像带索引的 Series 字典,提取、设置、删除列的操作与字典类似

用方法链分配新列

  • DataFrame 提供了 assign() 方法,可以利用现有的列创建新列,assign 返回的都是数据副本,原 DataFrame 不变

索引 / 选择

img

数据对齐和运算

sd = {'one': [1, 2, 3, 4], 'two': [5, 6, 7, 8]}
d1 = pd.DataFrame(data=sd)

print(d1)
"""
   one  two
0    1    5
1    2    6
2    3    7
3    4    8
"""
print(d1 + d1)
"""
   one  two
0    2   10
1    4   12
2    6   14
3    8   16
"""

###布尔运算
d1 = pd.DataFrame({'a': [1, 0, 1], 'b': [0, 1, 1]}, dtype=bool)
d2 = pd.DataFrame({'a': [0, 1, 1], 'b': [1, 1, 0]}, dtype=bool)

print(d1 & d2)
"""
       a      b
0  False  False
1  False   True
2   True  False
"""

转置

sd = {'one': [1, 2, 3, 4], 'two': [5, 6, 7, 8]}
d1 = pd.DataFrame(data=sd)

print(d1)
"""
   one  two
0    1    5
1    2    6
2    3    7
3    4    8
"""
print(d1.T)
"""
     0  1  2  3
one  1  2  3  4
two  5  6  7  8
"""

DataFrame 应用 NumPy 函数

Series 与 DataFrame 可使用 log、exp、sqrt 等多种元素级 NumPy 通用函数(ufunc) ,假设 DataFrame 的数据都是数字。

sd = {'one': [1, 2, 3, 4], 'two': [5, 6, 7, 8]}
d1 = pd.DataFrame(data=sd)

print(d1)
"""
   one  two
0    1    5
1    2    6
2    3    7
3    4    8
"""
print(np.exp(d1))
"""
         one          two
0   2.718282   148.413159
1   7.389056   403.428793
2  20.085537  1096.633158
3  54.598150  2980.957987
"""
print(np.asarray(d1))
"""
[[1 5]
 [2 6]
 [3 7]
 [4 8]]
"""

Serics和DataFrame 的重构结构属性

  • rename,对标签名重命名,也可以重置index和columns的部分标签列信息,接收标量(用于对标签名重命名)或字典(用于重命名行标签和列标签)
  • reindex,接收一个新的序列与已有标签列匹配,当原标签列中不存在相应信息时,填充NAN或者可选的填充值
  • set_index/reset_index,互为逆操作,前者是将已有的一列信息设置为标签列,而后者是将原标签列归为数据,并重置为默认数字标签
  • set_axis,设置标签列,一次只能设置一列信息,与rename功能相近,但接收参数为一个序列更改全部标签列信息(rename中是接收字典,允许只更改部分信息)
  • rename_axis,重命名标签名,rename中也可实现相同功能