TOC
KINA

KINA-0

Start having fun with KINA right now!

Pandas标签库简介

Pandas是一个开源的Python分析结构化数据的扩展程序库,基础是Numpy。可以从各种文件格式如CSV、JSON、SQL、Excel等导入数据,灵活高效地处理各种数据集,广泛应用在各种数据分析领域。

官网:pandas.pydata.org
源代码:github pandas

import numpy as np
import pandas as pd

1 Pandas对象基础

1.1 一维对象:Series

一维对象Series面向向量,其索引即为标签。可通过pd.Series()创建Series对象

1.1.1 Series对象初始化

  • 字典创建法:直接将Python字典转化为Series对象
dict_v = {'a': 0, 'b': 0.25, 'c': 0.5, 'd': 0.75, 'e': 1}
sr = pd.Series(dict_v)
print(sr)
a    0.00
b    0.25
c    0.50
d    0.75
e    1.00
dtype: float64
  • 数组创建法:传入指定的列表、数组或张量,设置函数的参数:值 values、标签index。其中标签可省略,默认为从0开始的编号。
v = [1.5, 3, 4.5, 6, 7.5]
k = ['a', 'b', 'c', 'd', 'e']
sr = pd.Series(v, index=k)
print(sr)
a    1.5
b    3.0
c    4.5
d    6.0
e    7.5
dtype: float64

1.1.2 Series对象的属性

Series对象有两个属性:值values、标签index
无论是用列表、NumPy数组还是PyTorch张量来创建对象,最终的值均为NumPy数组。因此调用values即可将Pandas的Series对象退化为NumPy数组。

v = np.array([53, 64, 72, 82])
k = ['1 号', '2 号', '3 号', '4 号']
sr = pd.Series(v, index=k)
print(sr, '\n')

print(sr.values)    # 查看values属性
print(sr.index)     # 查看index属性
1 号    53
2 号    64
3 号    72
4 号    82
dtype: int64 

[53 64 72 82]
Index(['1 号', '2 号', '3 号', '4 号'], dtype='object')

1.2 二维对象:DataFrame

二维对象DataFrame面向矩阵,其不仅有行标签 ,还有列标签。可通过pd.DataFrame()创建DataFrame对象

1.2.1 DataFrame对象初始化

  • 字典创建法:基于多个Series对象,每一个Series就是一列数据。传入一个Python字典,其每个键值对为列标签该列的Series对象
v1 = [53, 64, 72, 82]
v2 = ['女', '男', '男', '女']
i = ['1 号', '2 号', '3 号', '4 号']
sr1 = pd.Series(v1, index=i)
sr2 = pd.Series(v2, index=i)

df = pd.DataFrame({'年龄': sr1, '性别': sr2})
print(df)
     年龄 性别
1 号  53  女
2 号  64  男
3 号  72  男
4 号  82  女

若sr1和sr2的index不完全一致,则二维对象会取两者的并集,因此该对象就会产生一定数量的缺失值NaN

  • 数组创建法:传入指定的列表、数组或张量,设置函数的参数:值values、行标签index、列标签columns。其中行、列标签可省略,默认为从0开始的编号。
v = np.array([[53, '女'], [64, '男'], [72, '男'], [82, '女']])  # 数字自动转为字符串
i = ['1 号', '2 号', '3 号', '4 号']
c = ['年龄', '性别']

df = pd.DataFrame(v, index=i, columns=c)
print(df)
     年龄 性别
1 号  53  女
2 号  64  男
3 号  72  男
4 号  82  女

1.2.2 DataFrame对象的属性

DataFrame对象有三个属性:值values、行标签index、列标签columns
与一维的Series对象同理,调用values属性即可将Pandas的DataFrame对象退化为NumPy数组。

v = np.array([[53, '女'], [64, '男'], [72, '男'], [82, '女']])  # 数字自动转为字符串
i = ['1 号', '2 号', '3 号', '4 号']
c = ['年龄', '性别']
df = pd.DataFrame(v, index=i, columns=c)
print(df, '\n')

arr = df.values
print(arr)
print(df.index)
print(df.columns, '\n')

arr = arr[:, 0].astype(int) # 提取0号列,并转化为整数型数组
print(arr)
     年龄 性别
1 号  53  女
2 号  64  男
3 号  72  男
4 号  82  女 

[['53' '女']
 ['64' '男']
 ['72' '男']
 ['82' '女']]
Index(['1 号', '2 号', '3 号', '4 号'], dtype='object')
Index(['年龄', '性别'], dtype='object') 

[53 64 72 82]

2 对象的索引

Pandas的索引机制与Python列表、NumPy数组基本一致,存在以下两种索引:

  • 显式索引 .loc[]:使用Pandas对象提供的标签索引,与其他索引的区别为访问切片时包含右端点
  • 隐式索引 .iloc[]:使用数组本身自带的从0开始的索引

与NumPy数组一样,切片仅是视图,若想创建新变量,使用.copy()方法即可。

2.1 一维对象的索引

索引一维对象时,可以省略lociloc,这样形式上就与NumPy数组一致。

v = [53, 64, 72, 82]
k = ['1号', '2号', '3号', '4号']
sr = pd.Series(v, index=k)
print(sr, '\n')

print(sr.loc['3号'], '\n')           # sr.iloc[2]
print(sr.loc[['1号', '3号']], '\n') # sr.iloc[[[0, 2]]
print(sr.loc['1号':'3号'])            # sr.iloc[0:3]
1号    53
2号    64
3号    72
4号    82
dtype: int64 

72 

1号    53
3号    72
dtype: int64 

1号    53
2号    64
3号    72
dtype: int64

2.2 二维对象的索引

在NumPy数组中,花式索引输出的是一个向量。但在Pandas二维对象中,考虑到其行列标签的信息不能丢失,输出的是矩阵。

i = ['1号', '2号', '3号', '4号']
v1 = [53, 64, 72, 82]
v2 = ['女', '男', '男', '女']
sr1 = pd.Series(v1, index=i)
sr2 = pd.Series(v2, index=i)
df = pd.DataFrame({'年龄': sr1, '性别': sr2})
print(df, '\n')

print(df.loc['1号', '年龄'], '\n')           # df.iloc[0, 0]
print(df.loc[['1号', '3号'], ['性别', '年龄']], '\n')   # df.iloc[[0, 2], [1, 0]]
print(df.loc['1号':'3号', '年龄'], '\n')        # df.iloc[0:3, 0]
print(df.loc['3号', :], '\n')    # 提取行;df.iloc[2, :];可省略冒号
print(df.loc[:, '年龄'])        # 提取列;df.iloc[:, 0];可省略冒号与loc/iloc
    年龄 性别
1号  53  女
2号  64  男
3号  72  男
4号  82  女 

53 

   性别  年龄
1号  女  53
3号  男  72 

1号    53
2号    64
3号    72
Name: 年龄, dtype: int64 

年龄    72
性别     男
Name: 3号, dtype: object 

1号    53
2号    64
3号    72
4号    82
Name: 年龄, dtype: int64

3 对象的变形

3.1 转置:.T

调用T获取转置后的对象,用于处理某些行是特征、列是个体的畸形原始数据。

v = [[53, 64, 72, 82], ['女', '男', '男', '女']]
i = ['年龄', '性别']
c = ['1号', '2号', '3号', '4号']
df = pd.DataFrame(v, index=i, columns=c)
print(df, '\n')

df = df.T
print(df)
    1号  2号  3号  4号
年龄  53  64  72  82
性别   女   男   男   女 

    年龄 性别
1号  53  女
2号  64  男
3号  72  男
4号  82  女

3.2 翻转

利用切片机制对对象进行左右翻转.iloc[:, ::-1]与上下翻转.iloc[::-1, :]

i = ['1号', '2号', '3号', '4号']
v1 = [53, 64, 72, 82]
v2 = ['女', '男', '男', '女']
sr1 = pd.Series(v1, index=i)
sr2 = pd.Series(v2, index=i)
df = pd.DataFrame({'年龄': sr1, '性别': sr2})
print(df, '\n')

print(df.iloc[:, ::-1], '\n')   # 左右翻转
print(df.iloc[::-1, :])         # 上下翻转
    年龄 性别
1号  53  女
2号  64  男
3号  72  男
4号  82  女 

   性别  年龄
1号  女  53
2号  男  64
3号  男  72
4号  女  82 

    年龄 性别
4号  82  女
3号  72  男
2号  64  男
1号  53  女

3.3 重塑

类似PyThon字典,可以直接利用[]运算符,将Series并入DataFrame,或从DataFrame分离Series

i = ['1号', '2号', '3号', '4号']
v1 = [10, 20, 30, 40]
v2 = ['女', '男', '男', '女']
v3 = [1, 2, 3, 4]
sr1 = pd.Series(v1, index=i)
sr2 = pd.Series(v2, index=i)
sr3 = pd.Series(v3, index=i)
df = pd.DataFrame({'年龄': sr1, '性别': sr2})
print(df, '\n')

df['牌照'] = sr3  # 一维对象与二维对象的合并:把sr3并入,新建一列
print(df, '\n')

sr4 = df['年龄']  # 从中分离出sr4
print(sr4)
    年龄 性别
1号  10  女
2号  20  男
3号  30  男
4号  40  女 

    年龄 性别  牌照
1号  10  女   1
2号  20  男   2
3号  30  男   3
4号  40  女   4 

1号    10
2号    20
3号    30
4号    40
Name: 年龄, dtype: int64

3.4 拼接:pd.concat()

函数pd.concat()可以拼接两个对象,与np.concatenate()函数语法相似。一维对象Series与二维对象DataFrame的合并无需使用该函数,实为3.3重塑中的合并操作。

Pandas放弃了Python集合与字典的索引唯一特性,因此合并后的索引可能重复。可通过对对象的indexcolumns属性调用.is_unique()方法来检查是否有重复索引。

# 一维对象的合并
v1 = [10, 20, 30, 40]
v2 = [40, 50, 60]
k1 = ['1号', '2号', '3号', '4号']
k2 = ['4号', '5号', '6号']
sr1 = pd.Series(v1, index=k1)
sr2 = pd.Series(v2, index=k2)
print(sr1, '\n')
print(sr2, '\n')

print(pd.concat([sr1, sr2]))
1号    10
2号    20
3号    30
4号    40
dtype: int64 

4号    40
5号    50
6号    60
dtype: int64 

1号    10
2号    20
3号    30
4号    40
4号    40
5号    50
6号    60
dtype: int64

合并二维对象时需设置axis参数,默认为0,axis=x意义与NumPy中同为沿轴x

# 二维对象的合并
v1 = [[10, '女'], [20, '男'], [30, '男'], [40, '女']]
v2 = [[1, '是'], [2, '是'], [3, '是'], [4, '否']]
v3 = [[50, '男', 5, '是'], [60, '女', 6, '是']]
i1 = ['1 号', '2 号', '3 号', '4 号']
i2 = ['1 号', '2 号', '3 号', '4 号']
i3 = ['5 号', '6 号']
c1 = ['年龄', '性别']
c2 = ['牌照', '是否参保']
c3 = ['年龄', '性别', '牌照', '是否参保']
df1 = pd.DataFrame(v1, index=i1, columns=c1)
df2 = pd.DataFrame(v2, index=i2, columns=c2)
df3 = pd.DataFrame(v3, index=i3, columns=c3)
print(df1, '\n')
print(df2, '\n')
print(df3, '\n')

print(pd.concat([df1, df2], axis=1), '\n')  # 合并列对象(添加列特征)
print(pd.concat([df1, df3]))                # 合并行对象(添加行个体)
     年龄 性别
1 号  10  女
2 号  20  男
3 号  30  男
4 号  40  女 

     牌照 是否参保
1 号   1    是
2 号   2    是
3 号   3    是
4 号   4    否 

     年龄 性别  牌照 是否参保
5 号  50  男   5    是
6 号  60  女   6    是 

     年龄 性别  牌照 是否参保
1 号  10  女   1    是
2 号  20  男   2    是
3 号  30  男   3    是
4 号  40  女   4    否 

     年龄 性别   牌照 是否参保
1 号  10  女  NaN  NaN
2 号  20  男  NaN  NaN
3 号  30  男  NaN  NaN
4 号  40  女  NaN  NaN
5 号  50  男  5.0    是
6 号  60  女  6.0    是

4 对象的运算

执行基本运算时也是按元素运算,且可以使用NumPy的各种函数。

4.1 对象与系数的运算

# 一维对象与系数的运算
sr = pd.Series([53, 64, 72], index=['1 号', '2 号', '3 号'])
print(sr, '\n')

print(sr + 10, '\n')
print(sr * 10, '\n')
print(sr ** 2)
1 号    53
2 号    64
3 号    72
dtype: int64 

1 号    63
2 号    74
3 号    82
dtype: int64 

1 号    530
2 号    640
3 号    720
dtype: int64 

1 号    2809
2 号    4096
3 号    5184
dtype: int64
# 二维对象与系数的运算
sr = pd.Series([53, 64, 72], index=['1 号', '2 号', '3 号'])
v = [[53, '女'], [64, '男'], [72, '男']]
df = pd.DataFrame(v, index=['1号', '2号', '3号'], columns=['年龄', '性别'])
print(df, '\n')

df['减法'] = df['年龄'] - 5
df['除法'] = df['年龄'] / 5
df['取余'] = df['年龄'] % 3
print(df)
    年龄 性别
1号  53  女
2号  64  男
3号  72  男 

    年龄 性别  减法    除法  取余
1号  53  女  48  10.6   2
2号  64  男  59  12.8   1
3号  72  男  67  14.4   0

4.2 对象与对象的运算

对象做运算,必须保证其都是数字型对象,两个对象之间的维度可以不同(会产生缺失值)。

# 一维对象之间的运算
v1 = [10, 20, 30, 40]
v2 = [1, 2, 3]
k1 = ['1号', '2号', '3号', '4号']
k2 = ['1号', '2号', '3号']
sr1 = pd.Series(v1, index=k1)
sr2 = pd.Series(v2, index=k2)
print(sr1, '\n')
print(sr2, '\n')

print(sr1 + sr2, '\n')
print(sr1 * sr2, '\n')
print(sr1 ** sr2)
1号    10
2号    20
3号    30
4号    40
dtype: int64 

1号    1
2号    2
3号    3
dtype: int64 

1号    11.0
2号    22.0
3号    33.0
4号     NaN
dtype: float64 

1号    10.0
2号    40.0
3号    90.0
4号     NaN
dtype: float64 

1号       10.0
2号      400.0
3号    27000.0
4号        NaN
dtype: float64
# 二维对象之间的运算
v1 = [[10, '女'], [20, '男'], [30, '男'], [40, '女']]
v2 = [2, 8, 8, 5]
i1 = ['1号', '2号', '3号', '4号']
c1 = ['年龄', '性别']
i2 = ['1号', '2号', '3号', '6号']
c2 = ['成绩']
df1 = pd.DataFrame(v1, index=i1, columns=c1)
df2 = pd.DataFrame(v2, index=i2, columns=c2)
print(df1, '\n')
print(df2, '\n')

df1['减法'] = df1['年龄'] - df2['成绩']
df1['除法'] = df1['年龄'] / df2['成绩']
df1['取余'] = df1['年龄'] % df2['成绩']
print(df1)
    年龄 性别
1号  10  女
2号  20  男
3号  30  男
4号  40  女 

    成绩
1号   2
2号   8
3号   8
6号   5 

    年龄 性别    减法    除法   取余
1号  10  女   8.0  5.00  0.0
2号  20  男  12.0  2.50  4.0
3号  30  男  22.0  3.75  6.0
4号  40  女   NaN   NaN  NaN

使用np.abs()np.cos()np.exp()np.log()等数学函数时,会保留索引。
Pandas中仍然存在布尔型对象,用法参考NumPy即可,此处不多赘述。


5 对象的缺失值

5.1 发现缺失值:.isnull()

使用.isnull()方法发现缺失值NaN,生成布尔型对象。方法.notnull()效果与之相反,相当于在前面加非号~

# 发现一维对象的缺失值
v = [53, None, 72, 82]
k = ['1号', '2号', '3号', '4号']
sr = pd.Series(v, index=k)
print(sr, '\n')

print(sr.isnull())
1号    53.0
2号     NaN
3号    72.0
4号    82.0
dtype: float64 

1号    False
2号     True
3号    False
4号    False
dtype: bool
# 发现二维对象的缺失值
v = [[None, 1], [64, None], [72, 3], [82, 4]]
i = ['1号', '2号', '3号', '4号']
c = ['年龄', '牌照']
df = pd.DataFrame(v, index=i, columns=c)
print(df, '\n')

print(df.isnull())
      年龄   牌照
1号   NaN  1.0
2号  64.0  NaN
3号  72.0  3.0
4号  82.0  4.0 

       年龄     牌照
1号   True  False
2号  False   True
3号  False  False
4号  False  False

5.2 剔除缺失值:.dropna()

使用.dropna()方法剔除缺失值,直接丢弃。

# 剔除一维对象的缺失值
v = [53, None, 72, 82]
k = ['1号', '2号', '3号', '4号']
sr = pd.Series(v, index=k)
print(sr, '\n')

print(sr.dropna())
1号    53.0
2号     NaN
3号    72.0
4号    82.0
dtype: float64 

1号    53.0
3号    72.0
4号    82.0
dtype: float64

二维对象中,要么单独剔除含有缺失值的行,要么剔除含有缺失值的列。默认剔除行,可设置参数axis='columns'来剔除列(极少用)。也可设置参数how='all'来只有当全部为缺失值时才剔除。

# 剔除二维对象的缺失值
v = [[None, 1], [None, None], [72, 3], [82, 4]]
i = ['1号', '2号', '3号', '4号']
c = ['年龄', '牌照']
df = pd.DataFrame(v, index=i, columns=c)
print(df, '\n')

print(df.dropna(), '\n')
print(df.dropna(axis='columns'), '\n')
print(df.dropna(how='all'))
      年龄   牌照
1号   NaN  1.0
2号   NaN  NaN
3号  72.0  3.0
4号  82.0  4.0 

      年龄   牌照
3号  72.0  3.0
4号  82.0  4.0 

Empty DataFrame
Columns: []
Index: [1号, 2号, 3号, 4号] 

      年龄   牌照
1号   NaN  1.0
3号  72.0  3.0
4号  82.0  4.0

5.3 填充缺失值:.fillna()

使用.fillna()方法填充缺失值,通常选用常数(0、均值…)、前值(method='ffill')或后值(method='bfill')来填充。

# 填充一维对象的缺失值
v = [53, None, 72, 82]
k = ['1号', '2号', '3号', '4号']
sr = pd.Series(v, index=k)
print(sr, '\n')

print(sr.fillna(0), '\n')
print(sr.fillna(np.mean(sr)), '\n')
print(sr.fillna(method='ffill'), '\n')
print(sr.fillna(method='bfill'))
1号    53.0
2号     NaN
3号    72.0
4号    82.0
dtype: float64 

1号    53.0
2号     0.0
3号    72.0
4号    82.0
dtype: float64 

1号    53.0
2号    69.0
3号    72.0
4号    82.0
dtype: float64 

1号    53.0
2号    53.0
3号    72.0
4号    82.0
dtype: float64 

1号    53.0
2号    72.0
3号    72.0
4号    82.0
dtype: float64
# 填充二维对象的缺失值
v = [[None, 1], [None, None], [72, 3], [82, 4]]
i = ['1号', '2号', '3号', '4号']
c = ['年龄', '牌照']
df = pd.DataFrame(v, index=i, columns=c)
print(df, '\n')

print(df.fillna(0), '\n')
print(df.fillna(np.mean(df)), '\n')
print(df.fillna(method='ffill'), '\n')
print(df.fillna(method='bfill'))
      年龄   牌照
1号   NaN  1.0
2号   NaN  NaN
3号  72.0  3.0
4号  82.0  4.0 

      年龄   牌照
1号   0.0  1.0
2号   0.0  0.0
3号  72.0  3.0
4号  82.0  4.0 

      年龄    牌照
1号  32.4   1.0
2号  32.4  32.4
3号  72.0   3.0
4号  82.0   4.0 

      年龄   牌照
1号   NaN  1.0
2号   NaN  1.0
3号  72.0  3.0
4号  82.0  4.0 

      年龄   牌照
1号  72.0  1.0
2号  72.0  3.0
3号  72.0  3.0
4号  82.0  4.0

6 数据分析

6.1 读取csv文件:pd.read_csv()

使用函数pd.read_csv()读取csv文件为DataFrame对象,参数index_col表示从第几列开始读取,默认为0。

df = pd.read_csv('data.csv')

6.2 聚合方法

调用.head()方法可仅输出前五行。除此之外NumPy中所有的聚合函数在Pandas中均有对象版的聚合方法,且均为忽略缺失值的安全版本。

df.head()   # 仅输出前五行

# 各种聚合函数,使用方式参考NumPy中的安全版本
df.max()
df.min()
df.mean()
df.std()
df.sum()

可使用.describe()描述方法直接查看所有聚合函数的信息。其中min、25%、50%、75%、max为把数据从小到大排序后的五个分位点,显然50%分位点即为中位数。如下例所示

v = [[None, 1], [None, 2], [72, 3], [82, 4]]
i = ['1号', '2号', '3号', '4号']
c = ['年龄', '牌照']
df = pd.DataFrame(v, index=i, columns=c)
print(df, '\n')

print(df.describe())
      年龄  牌照
1号   NaN   1
2号   NaN   2
3号  72.0   3
4号  82.0   4 

              年龄        牌照
count   2.000000  4.000000
mean   77.000000  2.500000
std     7.071068  1.290994
min    72.000000  1.000000
25%    74.500000  1.750000
50%    77.000000  2.500000
75%    79.500000  3.250000
max    82.000000  4.000000

6.3 数据透视:.pivot_table()

使用.pivot_table()方法可创建数据透视,用法如下:

# Output为考察的核心,研究其他特征Input_r、Input_c与之的关系
df.pivot_table(Output, index=Input_r, columns=Input_c)

另有两个用于分割的函数:pd.cut() 指定分割序列、pd.cut() 指定分割段数。详见以下示例

【例】以虚构的示例数据为例,以“是否生还”特征为考察的核心,研究其它特征与之的关系。

df = pd.read_csv('elimination.csv')
print(df, '\n')

# 一个特征
print(df.pivot_table('是否生还', index='性别'), '\n')
# 两个特征
print(df.pivot_table('是否生还', index='性别', columns='等级'), '\n')
# 三个特征,以18岁为分水岭分为两部分
age = pd.cut(df['年龄'], [0, 18, 120])
print(df.pivot_table('是否生还', index=['性别', age], columns='等级'), '\n')
# 四个特征,将费用自动分为两部分
fare = pd.qcut(df['费用'], 2)
print(df.pivot_table('是否生还', index=['等级', fare], columns=['性别', age]))

pivot_table

发表评论