一. 找到各个城市中销售额 第二 的订单
1.1 获取数据
# 先将三个excel 进行融合 一个excel 里面有三个 sheet
data = pd.read_excel("./teacher/电商数据.xlsx",sheet_name=["订单信息","订单详情","地区信息"])
df = pd.merge(pd.merge(data["订单详情"],data["订单信息"]),data["地区信息"])
1.2 根据城市进行分组,再根据订单ID进行分组,对每个订单金额进行求和,再按照金额 倒叙 排列
方法 1
df.groupby(by = "城市").apply(lambda x: x.groupby(by = "订单ID").订单金额.sum().sort_values(ascending = False))
这样会存在问题, 相同金额的订单,会分别排在 第一名 和 第二名 这样
城市 订单ID
三亚 230372 183.00
226977 129.90 这两个都是 129.9
228703 129.90
227758 103.15
228004 99.00
方法2
# df.groupby(by = "城市").apply(lambda x: x.groupby(by = "订单ID").订单金额.sum().sort_values(ascending = False))
def fo(x):
s1 = x.groupby(by = "订单ID").订单金额.sum().sort_values(ascending = False) # 这里的 x 仍然代表 每一个 df
# s1 获取的是按照订单id 计算 的 订单金额 的总和 并按照 金额从大到小排序
if s1.shape[0] == 1: # s1 返回的是series,如果他的(x,)x是1,就返回唯一值,否则返回第二大的值
return s1.iloc[0]
else:
return s1.iloc[1]
老二 = df.groupby(by = "城市").apply(fo).reset_index().rename(columns = {0:"金额"})
这里输出的都是每个城市 订单金额第二的城市 和金额
城市 金额
0 三亚 129.90
1 三明 1380.21
2 上海 998.00
3 上饶 2110.70
4 东莞 1298.10
已经求出来第二消费高的城市了,因为还需要知道订单信息,需要和df表合并
但是 "老二" 表 已经是聚合过的 (按照城市 计算过sum) ,所以 df表也需要 groupby 城市 和 订单id
1 . df表 先聚合
df.groupby(by=["城市","订单ID"]).订单金额.sum().reset_index()
城市 订单ID 订单金额
0 三亚 226977 129.90
1 三亚 227758 103.15
2 三亚 228004 99.00
3 三亚 228703 129.90
4 三亚 229312 91.05
2. 两表连接 , 找到 订单金额 为 第二名 的 订单信息
pd.merge(gp,老二,left_on =["城市","订单金额"], right_on= ["城市","金额"],how = "inner")
方法2
def fo(x): #x 依然代表 每个df
s1 = x.groupby("订单ID").agg({"订单金额":"sum"}).sort_values(by="订单金额",ascending=False)
return s1
a = df.groupby(by="城市").apply(fo)
这里是获取到 按照城市 金额从大到小的 信息
def foo(x):
x["排名序号"] = x.订单金额.rank(method="dense",ascending=False) # 加一列排名序号
return x.query("排名序号==2")
a.reset_index().groupby(by=["城市"]).apply(foo) #只拿排名序号为2的信息
二 . 层次索引
- stack : 把列索引 转换成 行索引
- unstack : 把行索引 转换成 列索引
- names=['国家', '省份', '订单年份', '订单月份', None]
b = df.groupby(by=[ '国家', '省份', '订单年份', '订单月份']).apply(lambda x : x.金额.sum()).unstack(level=[0,1]).fillna(0)
level 0 是国家 1 是省份 unstack 是把行索引 变成了列
三 . 空值填充
- fillna - value : 指定填充 fillna(0)
- method : ffill从前方找内容填充
- bfill从后方找内容填充
- 演示数据.区域.str.contains("汇总") contains 是包含汇总字段的
演示数据 = pd.read_excel("./02.行列管理及筛选.xlsx",sheet_name="删除间隔行").iloc[:,:3]
演示数据
第三季度各区预计销售额汇总 列1 列2
0 区域 产品分类 预计销售额
1 东区 服装 372960.1584
2 NaN 辅助用品 161573.9614
3 NaN 配件 3635719.8314
4 NaN 自行车 22059205.9118
5 东区汇总 NaN 26229459.863
6 南区 服装 281120.2381
修改列名
演示数据.columns = 演示数据.iloc[0]
将 0 区域 产品分类 预计销售额 这一行 作为 列名
fillna - value : 指定填充
- method : ffill从前方找内容填充
bfill从后方找内容填充
演示数据.区域 = 演示数据.区域.fillna(method="ffill",axis=0)
将 区域 这一列 的空值 按照从前方找内容方式 填充
区域 产品分类 预计销售额
0 区域 产品分类 预计销售额
1 东区 服装 372960.1584
2 东区 辅助用品 161573.9614
3 东区 配件 3635719.8314
4 东区 自行车 22059205.9118
5 东区汇总 NaN 26229459.863
6 南区 服装 281120.2381
将 各区汇总去除
演示数据 = 演示数据.loc[~演示数据.区域.str.contains("汇总")]
演示数据.区域.str.contains("汇总") 是挑选 字段 中 有汇总的
~ 是 没有汇总的
四. 空值删除
-
dropna(subset=["产品分类"]) 指定删除 产品分类的空值
五. 数据清洗
5.1 有三个csv 文件 是 "state-" 开头 ".csv" 结尾 的文件
glob.glob("./state-*.csv")
返回的是 一个列表 ,内容都是 state- 开头 .csv 结尾的文件路径
['.\\state-abbrevs.csv', '.\\state-areas.csv', '.\\state-population.csv']
5.2 读取数据(多个)
for f in filenames:
display(pd.read_csv(f).head(2))
d = dict()
for f in filenames:
n = f.split("-")[1].split(".")[0]
d[n] = pd.read_csv(f)
n 是 key, 分别是 abbrevs areas population
d[n] 是 值 ,就是 pd.read_csv(f) 读取的内容
所有 d["abbrevs"] 就可以获取内容
5.3 rename 改列名 merge进行合并
d["areas"] = d["areas"].rename(columns = {"area (sq. mi)":"area"} )
d["population"].rename(columns= {"state/region":"abbreviation"},inplace = True)
pop_abb = pd.merge(d["population"],d["abbrevs"],how = 'outer')
5.3 对空值进行 统计
abbreviation ages year population state
0 AL under18 2012 1117489.0 Alabama
1 AL total 2012 4817528.0 Alabama
2 AL under18 2010 1130966.0 Alabama
3 AL total 2010 4785570.0 Alabama
4 AL under18 2011 1125763.0 Alabama
... ... ... ... ... ...
2539 USA total 2010 309326295.0 NaN
2540 USA under18 2011 73902222.0 NaN
2541 USA total 2011 311582564.0 NaN
2542 USA under18 2012 73708179.0 NaN
2543 USA total 2012 313873685.0 NaN
pop_abb 原数据 是以上所示
- 可以使用 isnull 用bool值看是否为空值, 然后通过 sum() 进行计算,因为True 是 1, False 是 0
pop_abb.isnull().sum()
abbreviation 0
ages 0
year 0
population 20
state 96
dtype: int64
这样可以看出来 population 和 state 都为空值列
5.4 对空值进行填充
1 获取 state 那一列 中 为空的所有行数据
pop_abb.loc[pop_abb.state.isnull()]
abbreviation ages year population state
2448 PR under18 1990 NaN NaN
2449 PR total 1990 NaN NaN
2450 PR total 1991 NaN NaN
2451 PR under18 1991 NaN NaN
2452 PR total 1993 NaN NaN
... ... ... ... ... ...
2539 USA total 2010 309326295.0 NaN
2540 USA under18 2011 73902222.0 NaN
2541 USA total 2011 311582564.0 NaN
2542 USA under18 2012 73708179.0 NaN
2543 USA total 2012 313873685.0 NaN
2. state 列 是依据 abbreviation 进行填充的,查看 state列为空的 abbreviation 去重后有哪些
pop_abb.loc[pop_abb.state.isnull()].abbreviation.unique()
array(['PR', 'USA'], dtype=object)
3. 建立 字典 ,建立 abbreviation(键) 和 state(值)的关系
dict_abb = {"PR":"Puerto Rico","USA":"USA"}
4. k是pr 和 usa, 当 abbreviation为 usa 或者 pr 时,对应的state 变为 对应的值
for k in dict_abb :
pop_abb.loc[pop_abb.abbreviation == k,"state"] = dict_abb[k]
5. pop_abb.isnull().sum()
abbreviation 0
ages 0
year 0
population 20
state 0
dtype: int64
可以看出 state 空白值已被全部填充
六 . 不同的数据呈现方式
1. 二维表
6.1 unstack() 行索引 变成 列索引
data.groupby(by = ["订单年份","订单月份"]).金额.sum().index
names=['订单年份', '订单月份'])
data.groupby(by = ["订单年份","订单月份"]).金额.sum().unstack(level = 0)
这是年份,按照上面 index 年份 月份来的
6.2 交叉表
pd.crosstab(data["订单月份"],data["订单年份"])
6.3 透视 (数据必须是唯一的)
pd.pivot(data , index , columns) 透视数据 ,但是都是去重的(唯一的)
d = data.groupby(by = ["订单年份","订单月份"]).agg({"金额":"sum"}).reset_index()
订单年份 订单月份 金额
0 2013 7 196650
1 2013 8 172625
2 2013 9 23750
3 2013 10 189475
4 2013 11 271125
5 2014 2 103762
6 2014 3 13906
根据年份 月份 计算 的话,有些月份 数据会消失 ,因为没有订单的数据
pd.pivot(d,index = ["订单月份"], columns = ["订单年份"], values=["金额"])
订单年份 2013 2014 2015 2016
订单月份
1 NaN NaN NaN 56879.0
2 NaN 103762.0 NaN 71044.0
3 NaN 13906.0 4098.0 60800.0
4 NaN 6775.0 NaN 48793.0
5 NaN NaN NaN 106246.0
6 NaN NaN NaN 25037.0
7 196650.0 NaN 639547.0 8922.0
8 172625.0 NaN 81340.0 NaN
9 23750.0 NaN 98361.0 NaN
10 189475.0 NaN 89448.0 NaN
11 271125.0 NaN 86645.0 NaN
12 NaN NaN 229448.0 NaN
6.4 透视表 pd.pivot_table
pd.pivot_table(data,index = ["订单月份"], columns = ["订单年份"], values=["金额"],aggfunc="sum")
2. 将二维表转换 为 一维表
原数据
matrix = pd.pivot_table(data,index = ["订单月份"], columns = ["订单年份"], values=["金额"],aggfunc="sum")
matrix
金额
订单年份 2013 2014 2015 2016
订单月份
1 NaN NaN NaN 56879.0
2 NaN 103762.0 NaN 71044.0
3 NaN 13906.0 4098.0 60800.0
4 NaN 6775.0 NaN 48793.0
5 NaN NaN NaN 106246.0
6 NaN NaN NaN 25037.0
7 196650.0 NaN 639547.0 8922.0
8 172625.0 NaN 81340.0 NaN
9 23750.0 NaN 98361.0 NaN
pd.melt() 将二维表转成一维表
vec = pd.melt(matrix).rename(columns = {"value":"金额"})
vec
None 订单年份 金额
0 金额 2013 NaN
1 金额 2013 NaN
2 金额 2013 NaN
3 金额 2013 NaN
4 金额 2013 NaN
5 金额 2013 NaN
6 金额 2013 196650.0
7 金额 2013 172625.0
8 金额 2013 23750.0
9 金额 2013 189475.0
生成一列 订单月份 1-12 循环 四次
vec["订单月份"] = list(range(1,13))* matrix.shape[1]
将 生成一列 新的序列
vec.dropna().reset_index(drop = True)
案例 中国各个省份 销售了那些 品类
订单ID 订单年份 订单月份 产品名称 产品子类别 产品类别 省份 国家 数量 单价 金额
0 a01 2015 11 Touring Tire Tube 车胎和内胎 配件 黑龙江 中国 1 5 5
1 a02 2015 11 Short-Sleeve Classic Jersey S 骑行服 服装 内蒙古 中国 1 54 54
2 a03 2015 11 Touring-1000 Blue 46 旅行自行车 自行车 吉林 中国 1 2384 2384
3 a04 2015 7 Mountain-200 Silver 38 山地自行车 自行车 辽宁 中国 1 2320 2320
4 a05 2015 11 Touring Tire 车胎和内胎 配件 河北 中国 1 29 29
a = data.query("国家 == '中国'").groupby(by=["省份"]).apply(lambda x: "/".join(x["产品类别"].unique())).reset_index().rename(columns = {0:"品类们"})
按照 中国 各省份 进行分类 , .join 拼接 多个产品。 并进行 去重操作
b = data.query("国家 == '中国'").groupby(by=["省份"]).金额.sum().reset_index()
计算各个省份 的销售额
pd.concat([a,b],axis=1).iloc[:,[1,2,3]]
将 a b 进行左右拼接 去列 1,2,3列