天天看点

Pandas常用操作Series 的创建DataFrame的创建通过索引值或索引标签获取数据利用pandas查询数据利用pandas的DataFrames进行统计分析利用pandas实现SQL操作排序利用pandas进行缺失值的处理利用pandas实现Excel的数据透视表功能多层索引的使用

参考天池AI

github博客传送门

博客园传送门

安装pandas

通过命令提示符 pip install pandas

或者通过第三方发放版 Anaconda 进行鼠标操作安装

Numpy学习教程传送门

https://blog.csdn.net/zhanghao3389/article/details/82791862

Series 的创建

import numpy as np, pandas as pd

# 通过一维数组创建序列
arr1 = np.arange(10)  # 创建一个0~9的numpy数组对象
print(arr1)           # 打印这个数组
print(type(arr1))   #打印这个数组的类型
s1 = pd.Series(arr1) # 将数组转换为 Series
print(s1)             # 打印出这个Series
print(type(s1))       # 打印出这个Series的数据类型类型
                

通过字典的方式创建序列

dic1 = {'a': 10, 'b': 20, 'c': 30, 'd': 40, 'e': 50}  # 创建一个字典dic1
print(dic1)           # 打印这个字典
print(type(dic1))     # 打印这个字典的数据类型
s2 = pd.Series(dic1)  # 将这个字典转换为Series
print(s2)             # 打印转换后的Series
print(type(s2))       #打印转化后的Series数据类型 
                

DataFrame的创建

数据框的创建主要有三种方式

1.通过二维数组创建数据框

arr2 = np.array(np.arange(12)).reshape(4, 3)  # 创建一个0~11的数组,然后reshape成4*3的矩阵
print(arr2)               # 打印出这个矩阵
print(type(arr2))         # 打印出这个矩阵的数据类型
df1 = pd.DataFrame(arr2)  # 将这个矩阵转换为 DataFrame
print(df1)                # 打印出转换后的DataFrame
print(type(df1))          # 打印出这个DataFrame的数据类型
                

2.通过字典的方式创建数据框

(1)字典列表

dic2 = {'a': [1, 2, 3, 4], 'b': [5, 6, 7, 8], 'c': [9, 10, 11, 12], 'd': [13, 14, 15, 16]}  # 创建一个字典
print(dic2)        # 打印出这个字典的内容
print(type(dic2))  # 打印出这个字典的数据类型

df2 = pd.DataFrame(dic2)  # 将这个字典转换为DataFrame
print(df2)                # 打印出转化后的DataFrame
print(type(df2))          # 打印出这个DataFrame的数据类型
                

(2)嵌套字典

dic3 = {'one': {'a': 1, 'b': 2, 'c': 3, 'd': 4}, 'two': {'a': 5, 'b': 6, 'c': 7, 'd': 8},
        'three': {'a': 9, 'b': 10, 'c': 11, 'd': 12}}  # 创建了一个嵌套的字典
print(dic3)        # 打印出这个嵌套的字典
print(type(dic3))  # 打印出这个字典的数据类型

df3 = pd.DataFrame(dic3)  # 将这个嵌套字典转换为DataFrame
print(df3)                # 打印出转换后的DataFrame
print(type(df3))          # 打印出这个DataFrame的数据类型
                

3.通过数据框的方式创建数据框

df4 = df3[['one', 'three']]  # 通过调用df3中的两列数据进行创建DataFrame
print(df4)                   # 打印出这个调用df3中数据的DataFrame
print(type(df4))             # 打印出这个DataFrame的数据类型

s3 = df3['one']  # 通过调用df3中的一列数据进行创建DataFrame会创建出Series
print(s3)        # 打印出这个Series
print(type(s3))  # 打印出这个Series的数据类型
                

通过索引值或索引标签获取数据

import numpy as np, pandas as pd

s4 = pd.Series(np.array([1, 1, 2, 3, 5, 8]))  # 创建一个Series数据
print(s4)        # 打印出这个数据
print(s4.index)  # 打印出这个数据的索引
                

现在我们为序列设定一个自定义的索引值:

s4.index = ['a', 'b', 'c', 'd', 'e', 'f']  # 手动修改s4这个数据的索引(index)
print(s4)                             # 打印修改索引后的Series
print('s4[3]:\n', s4[3])              # 取出下标为 3 的数据
print('s4[e]:\n', s4['e'])            # 取出索引为 e 的数据
print('s4[1,3,5]:\n', s4[[1, 3, 5]])  # 取出下标为 1 3 5 的数据
print("s4[['a','b','d','f']]:\n", s4[['a', 'b', 'd', 'f']])  # 取出索引为 a b d f 的数据
print('s4[:4]:\n', s4[:4])            # 切片到下标为 4 的所有数据
print("s4['c':]:\n", s4['c':])        # 切片索引为 c 开始后面所有的数据
print("s4['b':'e']:\n", s4['b':'e'])  # 切片索引为 b 开始 e 结束(左闭右开)的所有数据
                

自动化对齐

如果有两个序列,需要对这两个序列进行算术运算,这时索引的存在就体现的它的价值了—自动化对齐.

s5 = pd.Series(np.array([10, 15, 20, 30, 55, 80]), index=['a', 'b', 'c', 'd', 'e', 'f'])  # 创建一个Series并指定索引
print(s5)       # 打印出这个Series

s6 = pd.Series(np.array([12, 11, 13, 15, 14, 16]), index=['a', 'c', 'g', 'b', 'd', 'f'])  # 创建一个Series并指定索引
print(s6)       # 打印出这个Series
print(s5 + s6)  # 将两个Series进行相加操作
print(s5 / s6)  # 将两个Series进行相除操作
# 由于s5中没有对应的g索引,s6中没有对应的e索引,所以数据的运算会产生两个缺失值NaN。
# 注意,这里的算术结果就实现了两个序列索引的自动对齐,而非简单的将两个序列加总或相除对于数据框的对齐,不仅仅是行索引的自动对齐,同时也会自动对齐列索引(变量名)
                

利用pandas查询数据

import pandas as pd

# 可以通过布尔索引有针对的选取原数据的子集、指定行、指定列等。
stu_dic = {'Age': [14, 13, 13, 14, 14, 12, 12, 15, 13, 12, 11, 14, 12, 15, 16, 12, 15, 11, 15],
           'Height': [69, 56.5, 65.3, 62.8, 63.5, 57.3, 59.8, 62.5, 62.5, 59, 51.3, 64.3, 56.3, 66.5, 72, 64.8, 67, 57.5, 66.5],
           'Name': ['Alfred', 'Alice', 'Barbara', 'Carol', 'Henry', 'James', 'Jane', 'Janet', 'Jeffrey', 'John',  'Joyce', 'Judy', 'Louise', 'Marry', 'Philip', 'Robert', 'Ronald', 'Thomas', 'Willam'],
           'Sex': ['M', 'F', 'F', 'F', 'M', 'M', 'F', 'F', 'M', 'M', 'F', 'F', 'F', 'F', 'M', 'M', 'M', 'M', 'M'],
           'Weight': [112.5, 84, 98, 102.5, 102.5, 83, 84.5, 112.5, 84, 99.5, 50.5, 90, 77, 112, 150, 128, 133, 85, 112]}
# 创建了一个DataFrame数据框
student = pd.DataFrame(stu_dic)
                

查询数据的前5行或末尾5行 student.head() student.tail()

print(student)                      # 打印这个数据框
print('前五行:\n', student.head())  # 查询这个数据框的前五行
print('后五行:\n', student.tail())  # 查询这个数据框的后五行
                

查询指定的行

print(student.loc[[0, 2, 4, 5, 7]])  # 这里的loc索引标签函数必须是中括号[]
                

查询指定的列

print(student[['Name', 'Height', 'Weight']].head())  # 如果多个列的话,必须使用双重中括号
                

也可通过loc索引标签查询指定的列

print(student.loc[:, ['Name', 'Height', 'Weight']].head)
                

查询出所有12岁以上的女生信息

print(student[(student['Sex'] == 'F') & (student['Age'] > 12)])
                

查询出所有12岁以上的女生姓名,身高和体重

print(student[(student['Sex'] == 'F') & (student['Age'] > 12)][['Name', 'Height', 'Weight']])
                

利用pandas的DataFrames进行统计分析

import numpy as np, pandas as pd

np.random.seed(1234)
d1 = pd.Series(2 * np.random.normal(size=100) + 3)
d2 = np.random.f(2, 4, size=100)
d3 = np.random.randint(1, 100, size=100)

print('非空元素计算: ', d1.count())       # 非空元素计算
print('最小值: ', d1.min())              # 最小值
print('最大值: ', d1.max())              # 最大值
print('最小值的位置: ', d1.idxmin())     # 最小值的位置,类似于R中的which.min函数
print('最大值的位置: ', d1.idxmax())     # 最大值的位置,类似于R中的which.max函数
print('10%分位数: ', d1.quantile(0.1))  # 10%分位数
print('求和: ', d1.sum())               # 求和
print('均值: ', d1.mean())              # 均值
print('中位数: ', d1.median())          # 中位数
print('众数: ', d1.mode())              # 众数
print('方差: ', d1.var())               # 方差
print('标准差: ', d1.std())             # 标准差
print('平均绝对偏差: ', d1.mad())       # 平均绝对偏差
print('偏度: ', d1.skew())             # 偏度
print('峰度: ', d1.kurt())             # 峰度
print('描述性统计指标: ', d1.describe())  # 一次性输出多个描述性统计指标
# 必须注意的是,descirbe方法只能针对序列或数据框,一维数组是没有这个方法的
                

这里自定义一个函数,将这些统计描述指标全部汇总到一起:

def stats(x):
    return pd.Series([x.count(), x.min(), x.idxmin(), x.quantile(.25), x.median(), x.quantile(.75),x.mean(), x.max(), x.idxmax(), x.mad(), x.var(), x.std(), x.skew(), x.kurt()],index=['Count', 'Min', 'Whicn_Min', 'Q1', 'Median', 'Q3', 'Mean', 'Max','Which_Max', 'Mad', 'Var', 'Std', 'Skew', 'Kurt'])

print(stats(d1))  # 打印统计后的指标
                

将这个函数 应用到每一列中

df = pd.DataFrame(np.array([d1,d2,d3]).T,columns=['x1','x2','x3'])
print(df.head())
print(df.apply(stats))
                

连续变量的相关系数(corr)和协方差矩阵(cov)的求解

print(df.corr())
                

相关系数的计算可以调用pearson方法或kendell方法或spearman方法,默认使用pearson方法。

print(df.corr('spearman'))
                

关注某一个变量与其余变量的相关系数的话,可以使用corrwith,如下方只关心x1与其余变量的相关系数

print(df.corrwith(df['x1']))
                

数值型变量间的协方差矩阵

print(df.cov())
                

利用pandas实现SQL操作

import pandas as pd, numpy as np

# 原数据
stu_dic = {'Age': [14, 13, 13, 14, 14, 12, 12, 15, 13, 12, 11, 14, 12, 15, 16, 12, 15, 11, 15],
           'Height': [69, 56.5, 65.3, 62.8, 63.5, 57.3, 59.8, 62.5, 62.5, 59, 51.3, 64.3, 56.3, 66.5, 72, 64.8, 67, 57.5, 66.5],
           'Name': ['Alfred', 'Alice', 'Barbara', 'Carol', 'Henry', 'James', 'Jane', 'Janet', 'Jeffrey', 'John', 'Joyce', 'Judy', 'Louise', 'Marry', 'Philip', 'Robert', 'Ronald', 'Thomas', 'Willam'],
           'Sex': ['M', 'F', 'F', 'F', 'M', 'M', 'F', 'F', 'M', 'M', 'F', 'F', 'F', 'F', 'M', 'M', 'M', 'M', 'M'],
           'Weight': [112.5, 84, 98, 102.5, 102.5, 83, 84.5, 112.5, 84, 99.5, 50.5, 90, 77, 112, 150, 128, 133, 85, 112]}
student = pd.DataFrame(stu_dic)  # 将数据转换为DataFrame
print(student)                   # 打印出这个数据
                

添加新行或增加新列

dic = {'Name': ['LiuShunxiang', 'Zhangshan'], 'Sex': ['M', 'F'], 'Age': [27, 23], 'Height': [165.7, 167.2],'Weight': [61, 63]}  # 需要增加的数据
student2 = pd.DataFrame(dic)  # 增加数据
print(student2)               # 打印出增加数据后的DataFrame
                

现在将student2中的数据新增到student中 可以通过 concat函数实现

student3 = pd.concat([student, student2])
print(student3)
                

注意 注意到了吗?在数据库中union必须要求两张表的列顺序一致,而这里concat函数可以自动对齐两个数据框的变量!

新增列的话,其实在pandas中就更简单了,例如在student2中新增一列学生成绩

print(pd.DataFrame(student2, columns=['Age', 'Weight', 'Name', 'Sex', 'Weight', 'Score']))
                

删除数据框student2通过del命令实现,该命令可以删除Python的所有对象

del student2  # 删除数据框 student2, 通过del命令可以删除Python的所有对象
print(student2)
                

删除指定的行

print(student.drop([0, 1, 3, 6]))
                

删除所有14岁以下的学生

print(student['Age'] > 14)
                

删除指定的列

print(student.drop(['Height', 'Weight'], axis=1).head())  # axis默认为0选择行
                

修改原始记录的 结合布尔索引和赋值的方法

student3.loc[student3['Name'] == 'LiuShunxiang', 'Height'] = 173
print(student3[student3['Name'] == 'LiuShunxiang'][['Name', 'Height']])
                

有关数据查询部分

聚合,排序和多表连接操作

聚合:pandas模块中可以通过groupby()函数实现数据的聚合操作

print(student.groupby('Sex').mean())
                

如果不对原始数据作限制的话,聚合函数会自动选择数值型数据进行聚合计算。如果不想对年龄计算平均值的话,就需要剔除改变量

print(student.drop('Age', axis=1).groupby('Sex').mean())
                

groupby还可以使用多个分组变量,例如根本年龄和性别分组,计算身高与体重的平均值

print(student.groupby(['Sex', 'Age']).mean())
                

对每个分组计算多个统计量

print(student.drop('Age', axis=1).groupby('Sex').agg([np.mean, np.median]))
                

排序

使用sort_index和sort_values实现序列和数据框的排序工作

Data = pd.Series(np.array(np.random.randint(1, 20, 10)))
print(Data)
print(Data.sort_index())
print(Data.sort_values(ascending=False))
                

数据框中一般都是按值排序

print(student.sort_values(by=['Age', 'Height']))
                

多表连接

多表之间的连接也是非常常见的数据库操作,连接分内连接和外连接,

在数据库语言中通过join关键字实现,pandas我比较建议使用merger函数实现数据的各种连接操作。

如下是构造一张学生的成绩表:

dic2 = {'Name': ['Alfred', 'Alice', 'Barbara', 'Carol', 'Henry', 'Jeffrey', 'Judy', 'Philip', 'Robert', 'Willam'], 'Score': [88, 76, 89, 67, 79, 90, 92, 86, 73, 77]}
score = pd.DataFrame(dic2)
print(score)
                

现在想把学生表student与学生成绩表score做一个关联

stu_score1 = pd.merge(student, score, on='Name')
print(stu_score1)
                

注意,默认情况下,merge函数实现的是两个表之间的内连接,即返回两张表中共同部分的数据。

可以通过how参数设置连接的方式,left为左连接;right为右连接;outer为外连接。

stu_score2 = pd.merge(student, score, on='Name', how='left')
print(stu_score2)
                

利用pandas进行缺失值的处理

三类方法 删除法 填补法 插值法

删除法:当数据中的某个变量大部分值都是缺失值,可以考虑删除改变量;当缺失值是随机分布的,且缺失的数量并不是很多是,也可以删除这些缺失的观测。

替补法:对于连续型变量,如果变量的分布近似或就是正态分布的话,可以用均值替代那些缺失值;如果变量是有偏的,可以使用中位数来代替那些缺失值;对于离散型变量,我们一般用众数去替换那些存在缺失的观测。

插补法:插补法是基于蒙特卡洛模拟法,结合线性模型、广义线性模型、决策树等方法计算出来的预测值替换缺失值。

import pandas as pd, numpy as np

stu_score = {'Score': [88.0, 76.0, 89.0, 67.0, 79.0, None, None, None, 90.0, None, None, 92.0, None, None, 86.0, 73.0, None, None, 77.0]}
stu_score2 = pd.DataFrame(stu_score)
s = stu_score2['Score']
print(s)
# 结合sum函数和isnull函数来检测数据中含有多少缺失值
print('缺失值个数:', sum(pd.isnull(s)))
                

直接删除缺失值

print('s.dropna():\n', s.dropna())
                

默认情况下,dropna会删除任何含有缺失值得行,我们再构造一个数据库试试

df = pd.DataFrame([[1, 1, 2], [3, 5, np.nan], [13, 21, 34], [55, np.nan, 10], [np.nan, np.nan, np.nan], [np.nan, 1, 2]], columns=('x1', 'x2', 'x3'))
print('df:\n', df)
print('df.dropna():\n', df.dropna())
                

使用一个常量来填补缺失值,可以使用fillna函数实现简单的填补工作

print('df.fillna(0):\n', df.fillna(0))  # 用 0 填补所有缺失值
                

采用前项填充或后项填充

print('method="ffill":\n', df.fillna(method='ffill'))
print('method="bfill":\n', df.fillna(method='bfill'))
                

使用常量填充不同的列

print("{'x1': 1, 'x2': 2, 'x3': 3}:\n", df.fillna({'x1': 1, 'x2': 2, 'x3': 3}))

x1_median = df['x1'].median()
x2_mean = df['x2'].mean()
x3_mean = df['x3'].mean()

print(x1_median)
print(x2_mean)
print(x3_mean)
print(df.fillna({'x1': x1_median, 'x2': x2_mean, 'x3': x3_mean}))
                

在使用填充法时,相对于常数填充或前项、后项填充,使用各列的众数、均值或中位数填充要更加合理一点,这也是工作中常用的一个快捷手段。

利用pandas实现Excel的数据透视表功能

import pandas as pd, numpy as np

# pivot_table(data, values=None, index=None, columns=None, aggfunc='mean', fill_value=None, margins=False, dropna=True, margins_name='ALL')
# data:需要进行数据透视表操作的数据框
# values:指定需要聚合的字段
# index:指定某些原始变量作为行索引
# columns:指定哪些离散的分组变量
# aggfunc:指定相应的聚合函数
# fill_value:使用一个常数替代缺失值,默认不替换
# margins:是否进行行或列的汇总,默认不汇总
# dropna:默认所有观测为缺失的列
# margins_name:默认行汇总或列汇总的名称为'All'

stu_dic = {'Age': [14, 13, 13, 14, 14, 12, 12, 15, 13, 12, 11, 14, 12, 15, 16, 12, 15, 11, 15],
           'Height': [69, 56.5, 65.3, 62.8, 63.5, 57.3, 59.8, 62.5, 62.5, 59, 51.3, 64.3, 56.3, 66.5, 72, 64.8, 67, 57.5, 66.5],
           'Name': ['Alfred', 'Alice', 'Barbara', 'Carol', 'Henry', 'James', 'Jane', 'Janet', 'Jeffrey', 'John', 'Joyce', 'Judy', 'Louise', 'Marry', 'Philip', 'Robert', 'Ronald', 'Thomas', 'Willam'],
           'Sex': ['M', 'F', 'F', 'F', 'M', 'M', 'F', 'F', 'M', 'M', 'F', 'F', 'F', 'F', 'M', 'M', 'M', 'M', 'M'],
           'Weight': [112.5, 84, 98, 102.5, 102.5, 83, 84.5, 112.5, 84, 99.5, 50.5, 90, 77, 112, 150, 128, 133, 85, 112]}
student = pd.DataFrame(stu_dic)
                

对一个分组变量(Sex),一个数值变量(Height)作统计汇总

Table1 = pd.pivot_table(student, values=['Height'], columns=['Sex'])
print(Table1)
                

对一个分组变量(Sex),两个数值变量(Height,Weight)做统计汇总

Table2 = pd.pivot_table(student, values=['Height', 'Weight'], columns=['Sex'])
print(Table2)
                

对两个分组变量(Sex, Age), 两个数值变量(Height, Weight)做统计汇总

Table3 = pd.pivot_table(student, values=['Height', 'Weight'], columns=['Sex', 'Age'])
print(Table3)
                

很显然这样的结果并不像Excel中预期的那样,该如何变成列联表的形式的?很简单,只需将结果进行非堆叠操作(unstack)即可

Table4 = pd.pivot_table(student, values=['Height', 'Weight'], columns=['Sex', 'Age']).unstack()
print(Table4)
                

使用多个聚合函数

Table5 = pd.pivot_table(student, values=['Height', 'Weight'], columns=['Sex'], aggfunc=[np.mean, np.median, np.std])
print(Table5)
                

有关更多数据透视表的操作,可参考http://python.jobbole.com/81212/

多层索引的使用

Series的层次化索引,索引是一个二维数组,相当于两个索引决定一个值

有点类似于DataFrame的行索引和列索引

import pandas as pd, numpy as np

s = pd.Series(np.arange(1, 10), index=[['a', 'a', 'a', 'b', 'b', 'c', 'c', 'd', 'd'], [1, 2, 3, 1, 2, 3, 1, 2, 3]])
print('s:\n', s)
print('s.index:\n', s.index)

# 选取外层索引为 a 的数据
print("s['a']:\n", s['a'])
# 选取外层索引为 a 和内层索引为 1 的数据
print("s['a', 1]:\n", s['a', 1])
# 选取外层索引为 a 和内层索引为 1,3的数据
print("s['a'][[1, 3]]:\n", s['a'][[1, 3]])
# 层次化索引的切片,包括右端的索引
print('s[["a", "c"]]:\n', s[['a', 'c']])
print('s["b":"d"]:\n', s['b':'d'])
# 通过unstack方法可以将Series变成一个DataFrame
# 数据的类型以及数据的输出结构都变成了DataFrame,对于不存在的位置使用NaN填充
print('s.unstack():\n', s.unstack())
                

DataFrame的层次化索引

data = pd.DataFrame(np.random.randint(0, 150, size=(8,12)),columns=pd.MultiIndex.from_product([['模拟考', '正式考'],['数学', '语文', '英语', '物理', '化学', '生物']]),index=pd.MultiIndex.from_product([['期中', '期末'],['雷军', '李斌'],['测试一', '测试二']]))
print('data:\n', data)

print('data["模拟考"]["语文","数学"]:\n', data['模拟考'][['语文', '数学']])
print("data.loc['期中', '雷军', '测试一']['模拟考', '数学']:\n", data.loc['期中', '雷军', '测试一']['模拟考', '数学'])
print("data.loc['期中', '雷军', '测试一']:\n", data.loc['期中', '雷军', '测试一'])

print("data['正式考']:\n", data['正式考'])
                

继续阅读