【Pandas】Pandas基础知识汇总

提示:该篇文章为自学笔记,bilibili学习视频出处bv: BV1UJ411A7Fs


1. Pandas作用

用于数据分析、数据处理和数据可视化。

2. Pandas数据读取

数据类型 说明 读取方法
csv、tsv、txt 用逗号分隔、tab分割的纯文本文件 pd.read_csv
json json格式 pd.read_json
excel xls或者xlsx文件 pd.read_excel
数据库 关系型数据库表 pd.read_sql

使用pandas首先要导入包:

import pandas as pd

2.1 读取csv文件

加载以逗号为分隔符的CSV(Comma-Separated Values)文件

语法: pd.read_csv(),参数如下:

  • sep: 指定分隔符
  • names: list类型,指定columns名称
  • engine: 使用的分析引擎。可以选择C或者是python。C引擎快但是Python引擎功能更加完备。
  • header: 用作列名的行号,以及数据。
    • 默认是infer,会将文件第一行数据作为列名,等同于header=0。
    • None,会默认生成数字0,1,2,3...作为列名。
    • 数字n,会将数据的第n行作为列名。

CSV文件的第一行指定列的数据头

如果CSV文件第一行没有数据头,read_csv参数中需要指定: header=None

# 从csv文件中加载数据集
dataframe = pd.read_csv(filepath_or_buffer="dataset_demo.csv", header="infer")

2.2 读取excel文件

  • pd.read_excel, 读取excel文件,参数如下:
    • skiprows: 忽略行数,pandas处理的时候会忽略前n行
# sheet_name用于指定数据在哪张表,可以写成表名称,也可以写成数据表所在位置的整数,也可以传入多张表,比如:sheet_name=[0, 1, 2, 3]
# header用于指定表头在哪一行
dataframe = pd.read_excel("dataset_demo.xlsx", sheet_name=0, header=0)
  • df.to_execl(): 将df数据存入到excel文件,参数如下:
    • index: False,存文件时不会把索引名称 存进去;为True则会连索引一并存储。

2.3 读取json文件

# orient:用来指定传入的json字符串类型:split, records, index, columns, values
# split: 用来读取有索引,由列字段和数据构成的json格式
# records: 用来读取成员为字典的列表
# index: 用来读取以索引为key,以列字段构成的字典为键值的json格式
# columns:处理以列为键,对应一个值字典的对象
# values: 处理一个嵌套的列表,里面的成员也是列表
dataframe = pd.read_json("dataset_demo.json", orient='records')

2.4 读取数据库

2.4.1 读取sqlite数据库

from sqlalchemy import create_engine
# 创建一个数据库连接
database_connection = create_engine('sqlite:///sample.db')

# 加载数据
dataframe = pd.read_sql_query('SELECT * FROM data', database_connection)

2.4.2 读取MySQL数据库

import pymysql
# 创建数据库连接
conn = pymysql.connect(
	host='127.0.0.1',
	user='root',
	password='123456',
	database='xxx',
	charset='utf8'
)
dataframe = pd.read_sql("select name from user where id = 3", con=conn)

2.5 查看数据

# 查看前几行数据,如果不指定n,默认输出前5条数据
dataframe.head(n=5)
# 查看数据的形状,返回类型为tuple,(行数,列数)
dataframe.shape
# 查看列名
dataframe.columns
# 查看索引信息
dataframe.index
# 查看每列的数据类型
dataframe.dtypes

3. pandas数据结构

3.1 DataFrame

DataFrame是二维数据。既有行索引index,也有列索引columns。
类型:

3.1.1 根据多个字典序列创建DataFrame

data = {
        'state': ['A', 'B', 'C', 'D'],
        'year': [2011, 2012, 2013, 2014],
        'pop': [12, 43, 46, 67]
    }
dataframe = pd.DataFrame(data)
print(dataframe)

运行结果:
【Pandas】Pandas基础知识汇总_第1张图片

3.1.2 多为数组创建DataFrame

data = [
    [1.74, 20, 65, '打球'],
    [1.75, 30, 64, '看书'],
    [1.78, 40, 65, '爬山']
]
col_names = ['身高', '年龄', '体重', '爱好']
df = pd.DataFrame(data=data, columns=col_names)
print('dataframe数据:\n', df)

运行结果:
【Pandas】Pandas基础知识汇总_第2张图片

3.1.3 查询DataFrame数据

# 查询一列数据,返回类型为Series
dataframe['year']

# 查询多列数据,返回类型为DataFrame
dataframe[['year', 'pop']]

# 查询一行数据,返回类型为Series
dataframe.loc[1]

# 查询多行数据,这里包括第1,2,3行,注意第3行也会包含,返回类型为DataFrame
dataframe.loc[1:3]

3.2 Series

Series: 一维数据,一行或一列。

3.2.1 使用list列表创建Series

s1 = pd.Series([1, 2, 3, 'a', 'b', 'c'])
print(s1)
# 查看Series的值,返回结果是一个数组[1 2 3 'a' 'b' 'c'],类型为
print(type(s1.values), s1.values)

运行结果:
【Pandas】Pandas基础知识汇总_第3张图片
也可以指定索引名称,替换掉自动生成的数字索引

s2 = pd.Series([1, 2, 3, 'a', 'b', 'c'], index=['num1', 'num2', 'num3', 'letter1', 'letter2', 'letter3'])
print(s2)

运行结果:
【Pandas】Pandas基础知识汇总_第4张图片

3.2.2 使用字典创建Series

使用字典生成的Series,索引为字典的key值

data = {"A": {"a": 1}, "B": "b", "C": "c"}
s3 = pd.Series(data)
print(s3)

运行结果:
【Pandas】Pandas基础知识汇总_第5张图片

3.2.3 根据标签索引查询数据

print("一个值: \n", s2['num1'])
print("多个值: \n", s2[['num1', 'letter2']])

【Pandas】Pandas基础知识汇总_第6张图片

4. Pandas查询数据

4.1 loc方法

根据行、列的标签值查询。

4.1.1 使用单个label值查询数据

得到单个值:

# 获取行索引为2,列名为‘身高’对应的值
dataframe.loc[2, '身高']

得到一个Series:

# 获取行索引为2,列名为'身高'和'体重'对应的值,返回类型为Series
dataframe.loc[2, ['身高', '体重']]

4.1.2 使用值列表批量查询

获取行索引为1和2,列索引为‘身高’数据,返回类型为Series

dataframe.loc[[1, 2], '身高']

获取行索引为1和2,列索引为‘身高’和’体重’的数据,返回类型为DataFrame

dataframe.loc[[1, 2], ['身高', '体重']]

4.1.3 使用数值区间进行范围查询

行索引按区间查询:

dataframe.loc[1:2, '身高']

列索引按区间查询:

dataframe.loc[1, '身高':'体重']

行和列都按区间查询:

dataframe.loc[1:2, '身高':'体重']

4.1.4 使用条件表达式查询

查询身高大于等于1.75的所有行记录:

# dataframe['身高'] >= 1.75 会将满足条件的索引传给loc。
dataframe.loc[dataframe['身高'] >= 1.75, :]

当有多个条件时,可以像下面这些写,&符号不要切换成and

dataframe.loc[(dataframe['身高'] >= 1.75) & (dataframe['体重'] >= 65), :]

4.1.5 调用函数查询

1)使用匿名表达式查询

dataframe.loc[lambda row: (row['身高'] >= 1.75) & (row['体重'] >= 65), :]

2)自定义函数查询

查找出爱好为看书的记录

def query_func(row):
    return row['爱好'] == '看书'

dataframe.loc[query_func, :]

5. 数据新增与更新

5.1 直接赋值

例1:让所有记录的体重列增加1kg

dataframe.loc[:, '体重'] = dataframe['体重'] + 1

例2: 新增列’身高/体重’,计算所有记录的该比值

dataframe.loc[:, '身高/比重'] = dataframe['身高'] / dataframe['体重']

或者写为如下形式

dataframe['身高/比重'] = dataframe['身高'] / dataframe['体重']

5.2 df.apply方法

对某一列统一做函数处理,注意axis=1表示的是列索引,axis=0表示的是行索引。

def weight_type(row):
    if row['体重'] <= 50:
        return "偏瘦"
    elif 50 < row['体重'] <= 65:
        return "适中"
    else:
        return "偏旁"


dataframe['结论'] = dataframe.apply(weight_type, axis=1)

5.3 df.assign方法

assign方法不会修改原有的dataframe

例1:将所有记录的体重翻倍,并赋给新列

new_df = dataframe.assign(t=lambda row: row['体重'] * 2)

5.4 按条件选择分组分别赋值

条件判断里写的时候需要注意,在python中1&符号连接多个条件来写。

# 新增一列,初始化都为''
dataframe['年龄段'] = ''
# 小于10岁的置为孩童
dataframe.loc[dataframe['年龄'] <= 10, '年龄段'] = '孩童'
# 大于10岁小于30岁的置为青年
dataframe.loc[(10 < dataframe['年龄']) & (dataframe['年龄'] <= 30), '年龄段'] = '青年'
# 大于30岁的置为中年
dataframe.loc[dataframe['年龄'] > 30, '年龄段'] = '中年'

查看dataframe:
【Pandas】Pandas基础知识汇总_第7张图片

6. Pandas数据统计函数

6.1 汇总类统计

  • 提取所有数字列统计结果
dataframe.describe()

【Pandas】Pandas基础知识汇总_第8张图片

  • 获取身高列的最小值
dataframe['身高'].min()
  • 获取年龄列的平均值
dataframe['年龄'].mean()

6.2 唯一去重和按值计数

  • 唯一性去重
# 获取爱好列中的所有爱好并去重
dataframe['爱好'].unique()
  • 按值计数
dataframe['爱好'].value_counts()

【Pandas】Pandas基础知识汇总_第9张图片

6.3 相关系数和协方差

6.3.1 概念

对于两个变量X、Y:

  • 协方差: 衡量同向反向程度,如果协方差为正,说明X,Y通向变化,协方差越大说明同向程度越高;如果协方差为负,说明X,Y反向运动,协方差越小说明反向程度越高。
  • 相关系数:衡量相似度程度,当他们的相关系数为1时,说明两个变量变化时的正向相似度最大,当相关系数为-1时,说明两个变量变化的反向相似度最大。

6.3.2 相关方法

  • 协方差矩阵
dataframe.cov()

【Pandas】Pandas基础知识汇总_第10张图片

  • 相关系数矩阵
dataframe.corr()

【Pandas】Pandas基础知识汇总_第11张图片

  • 单独计算相关系数

计算年龄和体重的相关系数

dataframe['年龄'].corr(dataframe['体重'])

7. Pandas对缺失值的处理

7.1 监测缺失值

  • isnull(): 判断df每个元素是否为null,是null为True,不是null为False。
dataframe.isnull()

【Pandas】Pandas基础知识汇总_第12张图片

单个列判断是否都为空:

dataframe['年龄'].isnull()
  • notnull():和isnull()相反,判断df各个元素是否不为null,不是null为True,是null为False。
dataframe.notnull()

【Pandas】Pandas基础知识汇总_第13张图片

筛选体重已登记的行:

dataframe.loc[dataframe['体重'].notnull(), :]

【Pandas】Pandas基础知识汇总_第14张图片

7.2 丢弃缺失值

  • dropna:丢弃、删除缺失值,以下是该函数的三个参数:
    • aixs:删除行还是列,{0 or ‘index’, 1 or ‘columns’}, default 0。
    • how:如果等于any则任何值为空都删除,如果等于all则所有值都为空才删除。
    • inplace:如果为true则修改当前df,否则返回新的df。

删除全是空值的列

dataframe.dropna(axis="columns", how='all', inplace=True)
print(dataframe)

删除全是空值的行

dataframe.dropna(axis="index", how='all', inplace=True)
print(dataframe)

7.3 填充缺失值

  • fillna:填充空值,参数如下:
    • value: 用于填充的值,可以是单个值,或者字典(key是列明,value是值)。
    • method: 等于ffile使用前一个不为空的值填充forword fill;等于bfill使用后一个不为空的值填充 backword fill。
    • axis: 按行还是列填充,{0 or ‘index’, 1 or ‘columns’}
    • inplace: 如果为true则修改当前df,否则返回新的df。

将体重为空的元素填充为100,默认是生成新的df,如果想在原有df上修改,需要添加参数inplace=True

dataframe.fillna({"体重": 100})

等同于

dataframe.loc[:, '体重'] = dataframe['体重'].fillna(100)
print(dataframe)

8. Pandas的SettingWithCopyWarning告警

pandas不允许先筛选子dataframe,再进行修改写入。

两种解决方案:

  • 使用.loc实现一个步骤直接修改源dataframe。
  • 先复制一个dataframe再一个步骤执行修改。

9. Pandas数据排序

9.1 Series排序

  • Series.sort_values(): 对Series进行排序,参数如下:
    • ascending: 默认为True升序排序,为False降序排序
    • inplace: 是否修改原始Series

例子1:对体重列进行升序排序

dataframe['体重'].sort_values()

例子2: 对体重列进行降序排列

dataframe['体重'].sort_values(ascending=False)

9.2 DataFrame排序

  • DataFrame.sort_values(): 对DataFrame进行排序,参数说明如下:
    • by: 字符串或者list<字符串>,单列排序或者队列排序
    • ascending: bool或者list,升序还是降序,如果是list对应by的多列
    • inplace: 是否修改原始DataFrame

例子1:单列排序
按照体重进行排序,默认升序

如果想要降序排列,只需要添加参数ascending=False即可。

dataframe.sort_values(by="体重")

【Pandas】Pandas基础知识汇总_第15张图片
例子2: 多列排序

按照年龄和体重排序

dataframe.sort_values(by=["年龄", "体重"])

按照年龄和体重排序,但是年龄按升序排,体重按降序排:

这种排序方法使用场景:假如给每个记录再添加一个肥胖级别,同一级别有多条数据,先按肥胖级别升序排列,排列之后,再按体重降序排列,这样就很容易看出每个肥胖级别的体重情况。

dataframe.sort_values(by=["年龄", "体重"], ascending=[True, False])

10. Pandas字符串处理

处理过程如下:
1)先获取Series的str属性,然后在属性上调用函数;
2)只能在字符串列上使用,不能数字列上使用;
3)DataFrame上没有str属性和处理方法;
4)Series.str并不是Python原生字符串,而是自己的一套方法,大部分和原生str很相似。

  • 字符串替换: replace

替换为阅读

dataframe['爱好'].str.replace("看", "阅读")

也可以写为如下形式,Series.str默认开启了正则表达式模式,也可以通过参数regex=False进行关闭。

dataframe['爱好'].str.replace("[看]", "阅读", regex=True)
  • 判断是不是数字: isnumeric
dataframe['爱好'].str.isnumeric()
  • 计算字符串长度: len
dataframe['爱好'].str.len()
  • 以特定字符/字符串开头: startswith
condition = dataframe['爱好'].str.startswith("爬")
print(dataframe[condition])
  • 包含特定字符/字符串: contains
condition = dataframe['爱好'].str.contains("爬")
print(dataframe[condition])

连续的字符串使用方法: dataframe['爱好'].str.replace('爱', ‘喜欢’).str.len(),中间的str不能省,这是因为每次字符串操作后返回的依然是一个Series对象,如果直接.len()会报错。

11. Pandas的axis参数

  • axis=0或者"index"

    • 如果是单行操作,就指的某一行
    • 如果是聚合操作,指的是跨行cross rows
  • axis=1或者"columns"

    • 如果是单列操作,就指的某一列
    • 如果是聚合操作,指的是跨列cross columns

例子1: 删除一行数据

dataframe.drop(1, axis=0, inplace=True)

例子2: 删除一列数据

dataframe.drop('爱好', axis=1, inplace=True)

例子3: 验证axis=0,如果是聚合操作,指的是跨行cross rows

下方代码是跨行求平均值

dataframe.mean(axis=0)

先看下运行结果,发现计算的是每一列的平均值。跨行指的就是列不动,从行的方向上依次计算每列的聚合操作结果
【Pandas】Pandas基础知识汇总_第16张图片

例子4: 验证 axis=1, 如果是聚合操作,指的是跨列cross columns

下方代码是跨列求平均值

dataframe.mean(axis=1)

从结果看出,计算的确实是每一行的平均值。跨列指的就是行不动,从列的方向上依次计算每行的聚合操作结果。
【Pandas】Pandas基础知识汇总_第17张图片

12. Pandas的索引index用途

用途:

  • 方便数据查询
  • 获得性能提升
  • 自动数据对齐功能
  • 更多数据结构支持

索引上的一些方法:

  • 索引是否单调递增,是返回True,否返回False
dataframe.index.is_monotonic_increasing
  • 索引是否唯一,是返回True,否返回False
dataframe.index.is_unique

12.1 使用index查询数据

将索引修改为user_id列,drop=False会让user_id保留在column

dataframe.set_index("user_id", inplace=True, drop=False)

【Pandas】Pandas基础知识汇总_第18张图片
drop=True之后,发现列user_id不见了。

dataframe.set_index("user_id", inplace=True, drop=True)

【Pandas】Pandas基础知识汇总_第19张图片
根据索引,查询id为2的数据

dataframe.loc[2].head()

查询结果:如果查询结果只有一条记录,会以键值对的形式展示出来.
【Pandas】Pandas基础知识汇总_第20张图片
如果查询结果有多条记录,会以表格形式展示出来。
【Pandas】Pandas基础知识汇总_第21张图片

12.2 使用index提升查询性能

  • 如果index是唯一的,Pandas会使用哈希表优化,查询性能为O(1);
  • 如果index不是唯一的,但是有序,Pandas会使用二分查找算法,查询性能为O(logN);
  • 如果index是完全随机的,那么每次查询都要扫描全表,查询性能为O(N)。

12.3 使用index自动对齐数据

参考下方代码,当两个Series相加时,相等的index对应的列会被对应相加,但是各自独有的index,相加后变为了NaN。

s1 = pd.Series([1, 2, 3], index=list("abc"))
s2 = pd.Series([4, 5, 6], index=list("bcd"))
print(s1)
print(s2)
print(s1+s2)

【Pandas】Pandas基础知识汇总_第22张图片

12.4 使用index更多更强大的数据结构支持

  • CategoricalIndex,基于分类数据的Index,提升xingn;
  • MultiIndex,多维索引,用于groupby多维聚合后结果等;
  • DatetimeIndex,时间类型索引,强大的日期和时间的方法支持。

13. Pandas的Merge语法

  • pd.merge(
    left: DataFrame | Series,
    right: DataFrame | Series,
    how: str = “inner”,
    on: IndexLabel | None = None,
    left_on: IndexLabel | None = None,
    right_on: IndexLabel | None = None,
    left_index: bool = False,
    right_index: bool = False,
    sort: bool = False,
    suffixes: Suffixes = (“_x”, “_y”),
    copy: bool = True,
    indicator: bool = False,
    validate: str | None = None,
    )
    • left, right: 要merge的dataframe或者有name的Series。
    • how: join类型, left, right, outer, inner
    • on: join的key,left和right都需要有这个key
    • left_on: left的df或者series的key
    • right_on: right的df或者series的key
    • left_index, right_index: 使用index而不是普通的column做join
    • suffixes: 两个元素的后缀,如果列有重名,自动添加后缀,默认是(‘_x’, ‘_y’)

左连接、右连接、内连接、外连接区别
【Pandas】Pandas基础知识汇总_第23张图片

14. Pandas的Concat合并

语法:pd.concat(objs, axis=0, join=‘outer’, ignore_index=False)

  • objs: 一个列表,可以是DataFrame或者Series,也可以是DataFrame和Series的混合列表。
  • axis: 默认是0,按行合并,如果等于1代表按列合并。
  • join: 合并的时候索引的对齐方式,默认是outer join,也可以是inner join。
  • ignore_index: 是否忽略掉原来的数据索引。

15. Pandas拆分

拆分: df.iloc[]
例子:

# 具体的索引,获取的是一个Series对象,取的是索引为2的行
df_ratings.iloc[2]

# 切片,取的是索引为[1, 7)的行
df_ratings.iloc[1:7]

# 取的是索引为4, 3, 0的行
df_ratings.iloc[[4, 3, 0]]

# boolean值列表,boolean值个数为索引个数,多一个或少一个都会报错,会把为true对应的行取出来
df_ratings.iloc[[True] * 100835]

16. Pandas分组统计groupby

groupby: 先对数据分组,然后在每个分组上应用聚合函数、转换函数。

16.1 groupby相关操作

  • 遍历groupby结果
g = df_ratings.loc[:, ['userId', 'movieId', 'rating']].groupby('movieId')

for name, df in g:
    print(name)
    print(df.head())

【Pandas】Pandas基础知识汇总_第24张图片

  • 获取单个分组的数据
g.get_group('1619')

16.2 groupby实例

  • 单个列groupby,查询所有数据列的统计

求电影的平均分

df_ratings.loc[:, ['movieId', 'rating']].groupby('movieId').mean().head()

【Pandas】Pandas基础知识汇总_第25张图片

  • 多个列groupby,查询所有数据列的统计

下方代码会先对userId分组,然后再对movieId分组,然后再求分组后的其他列的平均值。此时的userId和movieId变成了二级索引

df_ratings.loc[:, ['userId', 'movieId', 'rating']].groupby(['userId', 'movieId']).mean().head()

【Pandas】Pandas基础知识汇总_第26张图片

下方代码比上面的代码多了参数as_index=False,A和B不再是索引,而是结果中的一部分。

df_ratings.loc[:, ['userId', 'movieId', 'rating']].groupby(['userId', 'movieId'], as_index=False).mean().head()

【Pandas】Pandas基础知识汇总_第27张图片

  • 同时查看多种数据统计

求每部电影的评分总和、评分平均值、评分标准差

import numpy as np
df_ratings.loc[:, ['movieId', 'rating']].groupby('movieId').agg([np.sum, np.mean, np.std]).head()

从结果可以看出列分出了二级索引。
【Pandas】Pandas基础知识汇总_第28张图片

  • 查看单列的结果数据统计

分组之后获取某一列的总和、平均值和标准差

df_ratings.loc[:, ['movieId', 'rating']].groupby('movieId')['rating'].agg([np.sum, np.mean, np.std]).head()

发现二级索引没了,这里提前对分组后的列做了过滤,性能会更好。
【Pandas】Pandas基础知识汇总_第29张图片

  • 不同列使用不同的聚合函数

按电影id分组后,对评分求平均值和总和,对userId求个数。

df_ratings.loc[:, ['userId', 'movieId', 'rating']].groupby('movieId').agg({'rating': [np.sum, np.mean], 'userId': np.count_nonzero}).head()

【Pandas】Pandas基础知识汇总_第30张图片

17. Pandas分层索引

17.1 常用操作

  • 查看索引
    以下会生成一个二级索引
s = df_ratings.loc[:, ['userId', 'movieId', 'rating']].groupby(['userId', 'movieId']).mean().head()
s.index

【Pandas】Pandas基础知识汇总_第31张图片

  • 把二级索引变成列
# 不会修改源s
s.unstack()

【Pandas】Pandas基础知识汇总_第32张图片

  • 把所有索引都变成列
# 不会修改源s
s.reset_index()

【Pandas】Pandas基础知识汇总_第33张图片

  • 设置索引

将元数据的userId和movieId设置为索引。

df_ratings.set_index(['userId', 'movieId'], inplace=True)
  • 对索引排序
df_ratings.sort_index(inplace=True)

18. 数据转换函数map、apply、applymap

18.1 map

map只用于Series,实现每个值-》值的映射。
使用方法:

  • Series.map(dict)
hobby_type = {
    "打球": "运动",
    "看书": "文艺",
    "爬山": "运动"
}

dataframe['爱好类型'] = dataframe['爱好'].map(hobby_type)
print(dataframe)

【Pandas】Pandas基础知识汇总_第34张图片

  • Series.map(function)
hobby_type = {
    "打球": "运动",
    "看书": "文艺",
    "爬山": "运动"
}
dataframe['爱好类型'] = dataframe['爱好'].map(lambda x: hobby_type[x])
print(dataframe)

【Pandas】Pandas基础知识汇总_第35张图片

18.2 apply

apply用于Series实现每个值的处理,用于Dataframe实现某个轴的Series的处理。

  • Series.apply(function)
dataframe['爱好类型'] = dataframe['爱好'].apply(lambda x: hobby_type[x])
  • DataFrame.apply(function)
dataframe['爱好类型'] = dataframe.apply(lambda x: hobby_type[x['爱好']], axis=1)

18.3 applymap

只能用于DataFrame,用于处理该DataFrame的每个元素。

例子:

dataframe[['user_id', '身高', '年龄', '体重']].applymap(lambda x: int(x))

【Pandas】Pandas基础知识汇总_第36张图片

19. Pandas的stack和pivot实现数据透视

将列式数据变成二维交叉数据,便于分析,叫做重塑或透视。

透视的方法:

19.1 使用unstack实现数据二维透视

stack: DataFrame.stack(level=-1, dropna=True),将column变成index
level=-1代表多层索引的最内层,可以通过==0、1、2指定多层索引的对应层。

unstack: DataFrame.unstack(level=-1, fill_value=None),将index变成column。

例子:
原始数据如下:

【Pandas】Pandas基础知识汇总_第37张图片

unstack之后的数据如下:

【Pandas】Pandas基础知识汇总_第38张图片
stack之后的数据如下:

【Pandas】Pandas基础知识汇总_第39张图片
参考代码:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
pd.set_option('display.max_rows', 500)
pd.set_option('display.max_columns', 500)
pd.set_option('display.width', 1000)
# 读取评分数据
df_ratings = pd.read_csv('movies/ratings.csv', sep=",", engine='python', header='infer')
# 将时间戳转换为时间
df_ratings["pdate"] = pd.to_datetime(df_ratings["timestamp"], unit='s')
print(df_ratings[["rating"]].applymap(lambda x: int(x)))
df_group = df_ratings[["userId", "movieId", "rating"]].applymap(lambda x: int(x)).groupby([df_ratings["pdate"].dt.month, "rating"])["userId"].agg(pv=np.size)
df_stack = df_group.unstack()
print(df_stack.head(10))
df_stack.plot()
plt.legend(loc='upper center', bbox_to_anchor=(0.6, 0.95), ncol=3, fancybox=True, shadow=True)
plt.show()
print(df_stack.stack().head(10))

透视之后效果:
【Pandas】Pandas基础知识汇总_第40张图片

19.2 使用pivot简化透视

pivot: DataFrame.pivot(index=None, columns=None, values=None)

指定index、columns、values实现二维透视。

原始数据:
【Pandas】Pandas基础知识汇总_第41张图片

参考代码:

df_pivot = df.pivot("pdate", "rating", "pv")
df_pivot.plot()
plt.show()

透视效果:
【Pandas】Pandas基础知识汇总_第42张图片
pivot方法相当于对df使用set_index创建分层索引,然后调用unstack。

20. 参考资料:

Pandas官方中文文档: https://www.pypandas.cn/docs/getting_started/
电影数据集: https://grouplens.org/datasets/movielens/

你可能感兴趣的:(Python,pandas)