Pandas模块对于二维数据表的操作非常方便,尤其是能够实现类似于数据库中的SQL语句的功能,方便了对数据的增删查改。下面举例说明DataFrame数据的基本操作。
为了便于理解,对于每种操作,均列出相应的SQL语句作为参考。
初始化DataFrame
原始数据展示
数据保存在Excel表格中,如下图所示,其中第一行是标题行。
数据共计12条,共有“序号”“英雄”“热度”“登场数”“被Ban数”5个字段。
读取数据至DataFrame
将数据由Excel表读取到DataFrame中,以便于后续在DataFrame中对数据进行操作。
import pandas as pd
path = r"D:\temp\KPL2023.xlsx" # Excel文件路径
data = pd.read_excel(path, header=0) # 读取数据(header=0表示第一行是标题行)
df = pd.DataFrame(data) # 将数据装入DataFrame中
print(df)
输出结果如下。说明数据已被读取入DataFrame中。
英雄 热度 登场数 被Ban数
0 大乔 T0 29 138
1 赵怀真 T0 42 104
2 公孙离 T0 61 58
3 海月 T1 36 53
4 明世隐 T1 41 45
5 项羽 T1 39 14
6 戈娅 T2 36 13
7 梦奇 T2 22 25
8 安琪拉 T3 5 3
9 瑶 T3 2 2
10 马超 T3 2 0
11 小乔 T3 1 0
数据查询
指定字段
SELECT 英雄, 登场数
FROM df
conse = df[["英雄","登场数"]]
print(conse)
输出结果如下:
英雄 登场数
0 大乔 29
1 赵怀真 42
2 公孙离 61
3 海月 36
4 明世隐 41
5 项羽 39
6 戈娅 36
7 梦奇 22
8 安琪拉 5
9 瑶 2
10 马超 2
11 小乔 1
条件查询
区间条件
查询满足要求的所有数据,要求某个字段的值大于或小于给定阈值。
SELECT * FROM df
WHERE 登场数>20 AND 被Ban数>50
condition = (df["登场数"] > 20) & (df["被Ban数"] > 50)
conse = df[condition]
print(conse)
输出结果如下:
序号 英雄 热度 登场数 被Ban数
0 1 大乔 T0 29 138
1 2 赵怀真 T0 42 104
2 3 公孙离 T0 61 58
3 4 海月 T1 36 53
枚举条件
查询满足要求的所有数据,要求某个字段的值等于指定的多个值之一。
--IN
SELECT * FROM df
WHERE 热度 IN ("T0", "T1")
--NOT IN
SELECT * FROM df
WHERE 热度 NOT IN ("T0", "T1")
# 在("T0", "T1")之中
condition1 = df["热度"].isin(("T0", "T1"))
conse1 = df[condition1]
print(conse1)
# 不在("T0", "T1")之中
condition2 = ~df["热度"].isin(("T0", "T1"))
conse2 = df[condition2]
print(conse2)
输出结果如下:
序号 英雄 热度 登场数 被Ban数
0 1 大乔 T0 29 138
1 2 赵怀真 T0 42 104
2 3 公孙离 T0 61 58
3 4 海月 T1 36 53
4 5 明世隐 T1 41 45
5 6 项羽 T1 39 14
序号 英雄 热度 登场数 被Ban数
6 7 戈娅 T2 36 13
7 8 梦奇 T2 22 25
8 9 安琪拉 T3 5 3
9 10 瑶 T3 2 2
10 11 马超 T3 2 0
11 12 小乔 T3 1 0
数据排序
--单字段排序
SELECT * FROM df
ORDER BY df.热度 desc
--多字段排序
SELECT * FROM df
ORDER BY df.热度 desc, df.登场数
# 单字段排序
conse1 = df.sort_values("热度", ascending=False)
print(conse1)
# 多字段排序
conse2 = df.sort_values(by=["热度", "登场数"], ascending=[False, True])
print(conse2)
输出结果如下:
序号 英雄 热度 登场数 被Ban数
8 9 安琪拉 T3 5 3
9 10 瑶 T3 2 2
10 11 马超 T3 2 0
11 12 小乔 T3 1 0
6 7 戈娅 T2 36 13
7 8 梦奇 T2 22 25
3 4 海月 T1 36 53
4 5 明世隐 T1 41 45
5 6 项羽 T1 39 14
0 1 大乔 T0 29 138
1 2 赵怀真 T0 42 104
2 3 公孙离 T0 61 58
序号 英雄 热度 登场数 被Ban数
11 12 小乔 T3 1 0
9 10 瑶 T3 2 2
10 11 马超 T3 2 0
8 9 安琪拉 T3 5 3
7 8 梦奇 T2 22 25
6 7 戈娅 T2 36 13
3 4 海月 T1 36 53
5 6 项羽 T1 39 14
4 5 明世隐 T1 41 45
0 1 大乔 T0 29 138
1 2 赵怀真 T0 42 104
2 3 公孙离 T0 61 58
数据统计
行列数查询
print("行列数:", df.shape)
print("行数:", df.shape[0])
print("列数:", df.shape[1])
输出结果如下:
行列数: (12, 5)
行数: 12
列数: 5
数据条数统计
统计数据总条数,也可以统计指定字段的非空数据条数。
--求数据总条数
SELECT COUNT(*) FROM df
--求字段"热度"的非空数据条数
SELECT COUNT(热度) FROM df
# 求各个字段的非空数据条数
conse = df.count()
print(conse)
# 求字段"热度"的非空数据条数
conse = df["热度"].count()
print(conse)
输出结果如下:
序号 12
英雄 12
热度 12
登场数 12
被Ban数 12
dtype: int64
12
按字段求和、平均值等
SELECT SUM(登场数) FROM df
--其他诸如平均值、最大值、最小值等略
import numpy as np
conse1 = df["登场数"].sum()
conse2 = df["登场数"].mean()
conse3 = df["登场数"].max()
conse4 = df["登场数"].min()
print("求和:", conse1)
print("平均值:", conse2)
print("最大值:", conse3)
print("最小值:", conse4)
输出结果如下:
求和: 316
平均值: 26.333333333333332
最大值: 61
最小值: 1
统计指定数据出现次数
针对指定字段进行统计,列出该字段中所有结果的出现次数。
--按1个字段统计出现次数
SELECT COUNT(*) FROM df GROUP BY 热度
--按多个字段统计出现次数
SELECT COUNT(*) FROM df GROUP BY 热度, 英雄
# 求"热度"字段中各结果的出现次数
conse = df["热度"].value_counts()
print(conse)
# 多个字段求出现次数
conse = df[["热度","英雄"]].value_counts()
print(conse)
输出结果如下:
T3 4
T0 3
T1 3
T2 2
Name: 热度, dtype: int64
热度 英雄
T0 公孙离 1
大乔 1
赵怀真 1
T1 明世隐 1
海月 1
项羽 1
T2 戈娅 1
梦奇 1
T3 安琪拉 1
小乔 1
瑶 1
马超 1
dtype: int64
即热度为"T3"的数据共有4条,热度为"T0"的数据共有3条等等。
如果要查询指定数据在指定字段中的出现次数,可采用如下方法:
--查询热度为"T0"的数据条数
SELECT COUNT(*) FROM df WHERE 热度 = "T0"
--查询热度为"T0"且英雄为"公孙离"的数据条数
SELECT COUNT(*) FROM df WHERE 热度 = "T0" AND 英雄 = "公孙离"
# 查询"T0"在"热度"字段中的出现次数
conse = df["热度"].value_counts()["T0"]
print(conse)
# 查询["T0","公孙离"]组合在["热度","英雄"]字段组合中的出现次数
conse = df[["热度", "英雄"]].value_counts()["T0", "公孙离"]
print(conse)
输出结果如下:
3
1
即热度字段中"T0"出现了3次;而热度+英雄字段中"T0"+"公孙离"出现了1次。
分组统计(groupby)
--单分组条件
SELECT 热度, SUM(登场数) 登场数之和
FROM df
GROUP BY df.热度
--多分组条件
SELECT 热度, 英雄, SUM(登场数) 登场数之和, AVG(被Ban数) 平均被Ban数
FROM df
GROUP BY df.热度, df.英雄
# 按热度进行分组,统计每组的登场数之和
conse = df.groupby("热度").sum()["登场数"]
print(conse)
# 按热度+英雄进行分组,统计每组的登场数之和和被Ban数之和
# 本来想求被Ban数的平均值,但好像这种方法没找到
conse = df.groupby(["热度", "英雄"]).sum()[["登场数", "被Ban数"]]
conse.columns = ["登场数之和", "被Ban数之和"]
print(conse)
输出结果如下:
热度
T0 132
T1 116
T2 58
T3 10
Name: 登场数, dtype: int64
登场数之和 被Ban数之和
热度 英雄
T0 公孙离 61 58
大乔 29 138
赵怀真 42 104
T1 明世隐 41 45
海月 36 53
项羽 39 14
T2 戈娅 36 13
梦奇 22 25
T3 安琪拉 5 3
小乔 1 0
瑶 2 2
马超 2 0
也可以使用聚合函数agg。
import numpy as np
# 按照"热度"分组,分别统计各"热度"下的登场数之和
conse1 = df.groupby("热度").agg({"登场数":np.sum}) # 分类统计
conse1 = conse1.rename(columns={"登场数":"登场数总和"}) # 更改查询结果的字段名称
print(conse1)
# 按照"热度""英雄"分组,分别统计各"热度"下的登场数之和和平均被Ban数
conse2 = df.groupby(["热度", "英雄"]).agg({"登场数":np.sum, "被Ban数":np.mean}) # 分类统计
conse2 = conse2.rename(columns={"登场数":"登场数总和", "被Ban数":"平均被Ban数"}) # 更改查询结果的字段名称
print(conse2)
输出结果如下:
登场数总和
热度
T0 132
T1 116
T2 58
T3 10
登场数总和 平均被Ban数
热度 英雄
T0 公孙离 61 58.0
大乔 29 138.0
赵怀真 42 104.0
T1 明世隐 41 45.0
海月 36 53.0
项羽 39 14.0
T2 戈娅 36 13.0
梦奇 22 25.0
T3 安琪拉 5 3.0
小乔 1 0.0
瑶 2 2.0
马超 2 0.0
横向统计
横向统计用于将每条数据不同字段的值相加,例如将单科成绩相加以计算总成绩。
这里举例将"登场数"和"被Ban数"相加以求得总数。
SELECT t.*, SUM(t.登场数, t.被Ban数) AS 总数
FROM df
import numpy as np
# 将每条数据的"登场数"和"被Ban数"进行求和
conse = df
conse["总数"] = conse[["登场数", "被Ban数"]].sum(1)
print(conse)
输出结果如下:
序号 英雄 热度 登场数 被Ban数 总数
0 1 大乔 T0 29 138 167
1 2 赵怀真 T0 42 104 146
2 3 公孙离 T0 61 58 119
3 4 海月 T1 36 53 89
4 5 明世隐 T1 41 45 86
5 6 项羽 T1 39 14 53
6 7 戈娅 T2 36 13 49
7 8 梦奇 T2 22 25 47
8 9 安琪拉 T3 5 3 8
9 10 瑶 T3 2 2 4
10 11 马超 T3 2 0 2
11 12 小乔 T3 1 0 1
自定义统计
使用apply方法实现自定义统计。
# 求出登场数、被Ban数的最大值与最小值之和
# 使用apply方法,其中的函数使用了匿名函数形式
# axis=0表示纵向计算,axis=1表示横向计算
conse = df[["登场数", "被Ban数"]].apply(lambda x: x.max() + x.min(), axis = 0)
print(conse)
输出结果如下:
登场数 62
被Ban数 138
dtype: int64
数据修改、增加与删除
数据修改
将满足指定条件数据的指定字段改为指定值。
例如将热度为"T3"的数据登场数设为0。
UPDATE df
SET 登场数=0
WHERE 热度="T3"
conse = df
condition = df["热度"] == "T3"
conse.loc[condition, "登场数"] = 0
print(conse)
输出结果如下:
序号 英雄 热度 登场数 被Ban数
0 1 大乔 T0 29 138
1 2 赵怀真 T0 42 104
2 3 公孙离 T0 61 58
3 4 海月 T1 36 53
4 5 明世隐 T1 41 45
5 6 项羽 T1 39 14
6 7 戈娅 T2 36 13
7 8 梦奇 T2 22 25
8 9 安琪拉 T3 0 3
9 10 瑶 T3 0 2
10 11 马超 T3 0 0
11 12 小乔 T3 0 0
可见热度为"T3"的英雄登场数已被改为0。
数据增加
INSERT INTO df(序号, 英雄, 热度, 登场数, 被Ban数)
VALUES(13, "鲁班七号", "T2", 35, 6)
df_add = pd.DataFrame({"序号":[13], "英雄":["鲁班七号"], "热度":["T2"], "登场数":[35], "被Ban数":[6]})
conse = pd.concat([df, df_add]).reset_index(drop=True)
print(conse)
输出结果如下:
序号 英雄 热度 登场数 被Ban数
0 1 大乔 T0 29 138
1 2 赵怀真 T0 42 104
2 3 公孙离 T0 61 58
3 4 海月 T1 36 53
4 5 明世隐 T1 41 45
5 6 项羽 T1 39 14
6 7 戈娅 T2 36 13
7 8 梦奇 T2 22 25
8 9 安琪拉 T3 5 3
9 10 瑶 T3 2 2
10 11 马超 T3 2 0
11 12 小乔 T3 1 0
12 13 鲁班七号 T2 35 6
可见"鲁班七号"的相关数据已增加。
数据删除
例如删除热度为"T3"的数据。
DELETE FROM df
WHERE 热度 = "T3"
conse = df[df["热度"] != "T3"]
print(conse)
输出结果如下:
序号 英雄 热度 登场数 被Ban数
0 1 大乔 T0 29 138
1 2 赵怀真 T0 42 104
2 3 公孙离 T0 61 58
3 4 海月 T1 36 53
4 5 明世隐 T1 41 45
5 6 项羽 T1 39 14
6 7 戈娅 T2 36 13
7 8 梦奇 T2 22 25
可见热度为"T3"的数据已删除。