写点什么

Pandas 之: 深入理解 Pandas 的数据结构

发布于: 2021 年 06 月 11 日

简介

本文将会讲解 Pandas 中基本的数据类型 Series 和 DataFrame,并详细讲解这两种类型的创建,索引等基本行为。

使用 Pandas 需要引用下面的 lib:

In [1]: import numpy as np
In [2]: import pandas as pd
复制代码

Series

Series 是一维带 label 和 index 的数组。我们使用下面的方法来创建一个 Series:

>>> s = pd.Series(data, index=index)
复制代码

这里的 data 可以是 Python 的字典,np 的 ndarray,或者一个标量。

index 是一个横轴 label 的 list。接下来我们分别来看下怎么创建 Series。

从 ndarray 创建

s = pd.Series(np.random.randn(5), index=['a', 'b', 'c', 'd', 'e'])
sOut[67]: a -1.300797b -2.044172c -1.170739d -0.445290e 1.208784dtype: float64
复制代码

使用 index 获取 index:

s.indexOut[68]: Index(['a', 'b', 'c', 'd', 'e'], dtype='object')
复制代码

从 dict 创建

d = {'b': 1, 'a': 0, 'c': 2}
pd.Series(d)Out[70]: a 0b 1c 2dtype: int64
复制代码

从标量创建

pd.Series(5., index=['a', 'b', 'c', 'd', 'e'])Out[71]: a    5.0b    5.0c    5.0d    5.0e    5.0dtype: float64
复制代码

Series 和 ndarray

Series 和 ndarray 是很类似的,在 Series 中使用 index 数值表现的就像 ndarray:

s[0]Out[72]: -1.3007972194268396
s[:3]Out[73]: a -1.300797b -2.044172c -1.170739dtype: float64
s[s > s.median()]Out[74]: d -0.445290e 1.208784dtype: float64
s[[4, 3, 1]]Out[75]: e 1.208784d -0.445290b -2.044172dtype: float64
复制代码

Series 和 dict

如果使用 label 来访问 Series,那么它的表现就和 dict 很像:

s['a']Out[80]: -1.3007972194268396
s['e'] = 12.
sOut[82]: a -1.300797b -2.044172c -1.170739d -0.445290e 12.000000dtype: float64
复制代码

矢量化操作和标签对齐

Series 可以使用更加简单的矢量化操作:

s + sOut[83]: a    -2.601594b    -4.088344c    -2.341477d    -0.890581e    24.000000dtype: float64
s * 2Out[84]: a -2.601594b -4.088344c -2.341477d -0.890581e 24.000000dtype: float64
np.exp(s)Out[85]: a 0.272315b 0.129487c 0.310138d 0.640638e 162754.791419dtype: float64
复制代码

Name 属性

Series 还有一个 name 属性,我们可以在创建的时候进行设置:

s = pd.Series(np.random.randn(5), name='something')
sOut[88]: 0 0.1922721 0.1104102 1.4423583 -0.3757924 1.228111Name: something, dtype: float64
复制代码

s 还有一个 rename 方法,可以重命名 s:

s2 = s.rename("different")
复制代码

DataFrame

DataFrame 是一个二维的带 label 的数据结构,它是由 Series 组成的,你可以把 DataFrame 看成是一个 excel 表格。DataFrame 可以由下面几种数据来创建:

  • 一维的 ndarrays, lists, dicts, 或者 Series

  • 结构化数组创建

  • 2 维的 numpy.ndarray

  • 其他的 DataFrame

从 Series 创建

可以从 Series 构成的字典中来创建 DataFrame:

d = {'one': pd.Series([1., 2., 3.], index=['a', 'b', 'c']),'two': pd.Series([1., 2., 3., 4.], index=['a', 'b', 'c', 'd'])}
df = pd.DataFrame(d)
dfOut[92]: one twoa 1.0 1.0b 2.0 2.0c 3.0 3.0d NaN 4.0
复制代码

进行 index 重排:

pd.DataFrame(d, index=['d', 'b', 'a'])Out[93]:    one  twod  NaN  4.0b  2.0  2.0a  1.0  1.0
复制代码

进行列重排:

pd.DataFrame(d, index=['d', 'b', 'a'], columns=['two', 'three'])Out[94]:    two threed  4.0   NaNb  2.0   NaNa  1.0   NaN
复制代码

从 ndarrays 和 lists 创建

d = {'one': [1., 2., 3., 4.],'two': [4., 3., 2., 1.]}
pd.DataFrame(d)Out[96]: one two0 1.0 4.01 2.0 3.02 3.0 2.03 4.0 1.0
pd.DataFrame(d, index=['a', 'b', 'c', 'd'])Out[97]: one twoa 1.0 4.0b 2.0 3.0c 3.0 2.0d 4.0 1.0
复制代码

从结构化数组创建

可以从结构化数组中创建 DF:

In [47]: data = np.zeros((2, ), dtype=[('A', 'i4'), ('B', 'f4'), ('C', 'a10')])
In [48]: data[:] = [(1, 2., 'Hello'), (2, 3., "World")]
In [49]: pd.DataFrame(data)Out[49]: A B C0 1 2.0 b'Hello'1 2 3.0 b'World'
In [50]: pd.DataFrame(data, index=['first', 'second'])Out[50]: A B Cfirst 1 2.0 b'Hello'second 2 3.0 b'World'
In [51]: pd.DataFrame(data, columns=['C', 'A', 'B'])Out[51]: C A B0 b'Hello' 1 2.01 b'World' 2 3.0
复制代码

从字典 list 创建

In [52]: data2 = [{'a': 1, 'b': 2}, {'a': 5, 'b': 10, 'c': 20}]
In [53]: pd.DataFrame(data2)Out[53]: a b c0 1 2 NaN1 5 10 20.0
In [54]: pd.DataFrame(data2, index=['first', 'second'])Out[54]: a b cfirst 1 2 NaNsecond 5 10 20.0
In [55]: pd.DataFrame(data2, columns=['a', 'b'])Out[55]: a b0 1 21 5 10
复制代码

从元组中创建

可以从元组中创建更加复杂的 DF:

In [56]: 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}})   ....: Out[56]:        a              b             b    a    c    a     bA 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
复制代码

列选择,添加和删除

可以像操作 Series 一样操作 DF:

In [64]: df['one']Out[64]: a    1.0b    2.0c    3.0d    NaNName: one, dtype: float64
In [65]: df['three'] = df['one'] * df['two']
In [66]: df['flag'] = df['one'] > 2
In [67]: dfOut[67]: one two three flaga 1.0 1.0 1.0 Falseb 2.0 2.0 4.0 Falsec 3.0 3.0 9.0 Trued NaN 4.0 NaN False
复制代码

可以删除特定的列,或者 pop 操作:

In [68]: del df['two']
In [69]: three = df.pop('three')
In [70]: dfOut[70]: one flaga 1.0 Falseb 2.0 Falsec 3.0 Trued NaN False
复制代码

如果插入常量,那么会填满整个列:

In [71]: df['foo'] = 'bar'
In [72]: dfOut[72]: one flag fooa 1.0 False barb 2.0 False barc 3.0 True bard NaN False bar
复制代码

默认会插入到 DF 中最后一列,可以使用 insert 来指定插入到特定的列:

In [75]: df.insert(1, 'bar', df['one'])
In [76]: dfOut[76]: one bar flag foo one_trunca 1.0 1.0 False bar 1.0b 2.0 2.0 False bar 2.0c 3.0 3.0 True bar NaNd NaN NaN False bar NaN
复制代码

使用 assign 可以从现有的列中衍生出新的列:

In [77]: iris = pd.read_csv('data/iris.data')
In [78]: iris.head()Out[78]: SepalLength SepalWidth PetalLength PetalWidth Name0 5.1 3.5 1.4 0.2 Iris-setosa1 4.9 3.0 1.4 0.2 Iris-setosa2 4.7 3.2 1.3 0.2 Iris-setosa3 4.6 3.1 1.5 0.2 Iris-setosa4 5.0 3.6 1.4 0.2 Iris-setosa
In [79]: (iris.assign(sepal_ratio=iris['SepalWidth'] / iris['SepalLength']) ....: .head()) ....: Out[79]: SepalLength SepalWidth PetalLength PetalWidth Name sepal_ratio0 5.1 3.5 1.4 0.2 Iris-setosa 0.6862751 4.9 3.0 1.4 0.2 Iris-setosa 0.6122452 4.7 3.2 1.3 0.2 Iris-setosa 0.6808513 4.6 3.1 1.5 0.2 Iris-setosa 0.6739134 5.0 3.6 1.4 0.2 Iris-setosa 0.720000
复制代码

注意, assign 会创建一个新的 DF,原 DF 保持不变。

下面用一张表来表示 DF 中的 index 和选择:

本文已收录于 http://www.flydean.com/03-python-pandas-data-structures/

最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!

欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!

发布于: 2021 年 06 月 11 日阅读数: 9
用户头像

关注公众号:程序那些事,更多精彩等着你! 2020.06.07 加入

最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧,尽在公众号:程序那些事!

评论

发布
暂无评论
Pandas之:深入理解Pandas的数据结构