pandas相关函数sort_values、字符串处理、index、merge、数据合并cancat、groupby分组统计

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

提示:这里可以添加本文要记录的大概内容:
1、pandas排序函数sort_values()
2、pandas字符串处理
3、index
4、merge
5、contact
6、groupby
7、数据转换
8、数据透视
9、日期处理
10、图相关

https://www.bilibili.com/video/BV1UJ411A7Fs?p=19


提示:以下是本篇文章正文内容,下面案例可供参考

一、排序函数sort_values()

pandas数据排序sort_values()
1、series的排序:serie.sort_value(ascending=True,inplace=Flase)
参数:ascending:默认为true升序排列,false降序排列;inplace:是否修改原始series
2、dataframe:dataframe.sort_values(by,ascending=True,inplace=False)
参数说明:by:指定排序的列或多列,是一个字符串或list;ascebding同上,inplace同上

#单列降序排列
df.sort_values(by="最高温度",ascending=False)
#多列降序排列
df.sort_values(by=["最高温度""温差"],ascending=False)
#多列分别指定降序升序
df.sort_values(by=["最高温度""温差"],ascending=[True,False])

二、字符串处理

1.介绍

a。使用方法:先获取series的str属性,然后在属性上调用函数
b。只能在字符串列上使用,不能在数字列上使用
c。dataframe上没有str属性和处理方法
d。series.str并不是python上原生字符串,而是自己的一套方法,不过大部分和原生str很相似
e。pandas的字符串方法列表参考文档:https://pandas.pydata.org/pandas-docs/stable/reference/series.html#string-handling链接

2.代码介绍

1、获取series的str属性,然后使用各种字符串处理函数
2、使用str 的startswith、contains等bool类series可以做条件查询
3、需要多次str处理的链式操作
4、使用正则表达式处理

代码如下(示例):

#获取列的数据类型
df.dtypes
#字符串替换函数
df["最高温度"].str.replace("℃","")
#判断是不是数字
df["最高温度"].str.isnumeric()
#查看字符串长度
df["最高温度"].str.len()

2、使用str 的startswith、contains等bool类series可以做条件查询

#下一步操作出来的结果是一个bool列
condition=df["日期"].str.startswith("2018-03")
#下一步出来的才是筛选列
df[condition]

在这里插入图片描述
3、需要多次str处理的链式操作
先将日期中018-03-02替换成20180302,再提取月份字符串201803

df["日期"].str.replace("-","").str.slice(0,6)
#以下也行
df["日期"].str.replace("-","").str[0:6]

4、使用正则表达式处理

def get_nianyueri(x):
    year,month,day=x["日期"].split("-")
    return f"{year}年{month}月{day}日"
df["中文日期"]=df.apply(get_nianyueri,axis=1)
df.head()
#去除年月日
df["中文日期"].str.replace("年","").str.replace("月","").str.replace("日","")
#正则表达式去除
df["中文日期"].str.replace("[年月日]","")

3.Categorical类型降低数据存储提升计算速度

运行原理:比如有一列性别都是男女这样的字符串,将其变成数字存储,男变成1,女变成2
在这里插入图片描述

运用场景:数据量特别大,已经超过100MB 的情况下使用。比如像以下的dataframe:存储量43.9+,这个+是因为数据类型是Object,object是对象的指针,并没有算指针指向的字符串的大小,指向存储数据的地方,所以这就导致实际存储数据的大小要比43.9要大得多,这种情况下,数据量一大就严重拖累运算速度。使用了categorical后,字符串变成了数字,字符串不会重复存储了,并且这样运行速度会大幅度提高
在这里插入图片描述

代码如下(示例):

import pandas as pd
import numpy as np
df=pd.read_excel(r"F:\work\ashimen\数据.xlsx")
df.info()
#找指针指向的字符串一起的存储大小
df.info(memory_usage="deep")
df_cat=df.copy()

#使用categorical类型降低存储量
df_cat["街道乡镇"]=df_cat["街道乡镇"].astype('category')
df_cat["社区村组"]=df_cat["社区村组"].astype('category')
df_cat.info(memory_usage="deep")
df_cat.head()#可以看到不影响数据
df_cat["街道乡镇"].value_counts()

关于变化后,存储大小的比对:
在这里插入图片描述
在这里插入图片描述

三、pandas索引index

1.介绍

index的用途:
1.更方便的数据查询;
2.使用index可以获得性能提升;
3.自动的数据对齐功能;
4.更多更强大的数据结构支持

2.代码介绍

1、使用index查询数据
代码如下(示例):

#drop==false,让索引列还保持在column,将乡镇列设为索引,并且让索引列保存到原表中
df.set_index("乡(镇)",inplace=True,drop=False)
df.index
#使用index的查询方法
df.loc['蒙镇'].head()
#使用column的condition查询方法
df.loc[df["乡(镇)"]=='蒙镇'].head(3)

2、使用index会提升查询性能
如果index是唯一的,pandas会使用哈希表优化,查询性能为O(1)
如果index不是唯一的,但是有序的,pandas会使用二分查找算法,查询性能为O(logn)
如果index是完全随机的,那么每次查询都要扫描全表,查询性能是O(n)

#查询索引是否递增
df.index.is_monotonic_increaseing
#查询索引是否唯一
df.index.is_unique

3.自动的数据对齐功能;

import pandas as pd
s1=pd.Series([1,2,3],index=list("abc"))
s1
s2=pd.Series([2,3,4],index=list("bcd"))
s2
s1+s2

输入的两个dataframe
相加后运行结果
4.index有更多更强大的数据结构支持;
很多强大的索引数据结构
a。CategoricalIndex,基于分类数据的index,提升性能;
b。MultiIndex,多维索引,用于groupby多维聚合后结果等;
C。DatetimeIndex,时间类型索引,强大的日期和时间的方法支持

四、pandas的merge()

pandas的merge,相当于sql的join,将不同的表按key关联到一个表

1.merge的语法

pd.merge(left,right,how=‘inner’,on=None,left_on=None,right_on=None,left_index=False,right_index=False,sort=Ture,suffixes=(‘_x’,‘_y’),copy=Ture,indicator=False,volidate=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做on
*suffixes:两个元素的后缀,如果列有重名,自动添加后缀,默认是_x _y

2.理解merge的一对一、一对多、多对多的数量对齐关系

1、一对一:关联的key都是唯一的

left=pd.DataFrame({'sno':[1,2,3,4],'name':['aaa','bbb','c','d']})
left
right=pd.DataFrame({'sno':[1,2,3,4],'age':['21','22','23','24']})
right
#一对一关系,结果中有四条
pd.merge(left,right,on='sno')

运行结果

   sno	name
0	1	aaa
1	2	bbb
2	3	c
3	4	d
   sno	age
0	1	21
1	2	22
2	3	23
3	4	24
   sno	name age
0	1	aaa	21
1	2	bbb	22
2	3	c	23
3	4	d	24

2、一对多:左边的表key唯一,右边不唯一

import pandas as pd
left=pd.DataFrame({'sno':[1,2,3,4],'name':['aaa','bbb','c','d']})
left
right=pd.DataFrame({'sno':[1,1,3,3,4],'grade':['math80','english91','chinese99','math24','english64']})
right
#有5行
pd.merge(left,right,on='sno')
   sno	name
0	1	aaa
1	2	bbb
2	3	c
3	4	d
	sno	grade
0	1	math80
1	1	english91
2	3	chinese99
3	3	math24
4	4	english64
	sno	name	grade
0	1	aaa	math80
1	1	aaa	english91
2	3	c	chinese99
3	3	c	math24
4	4	d	english64

3、多对多:左边、右边不唯一
结果会出现左边的行数*右边的行数

import pandas as pd
left=pd.DataFrame({'sno':[1,1,3,3],'爱好':['画画','篮球','c足球','d画画']})
left
right=pd.DataFrame({'sno':[1,1,3,3,4],'grade':['math80','english91','chinese99','math24','english64']})
right
pd.merge(left,right,on='sno')
 	sno	爱好
0	1	画画
1	1	篮球
2	3	c足球
3	3	d画画
	sno	grade
0	1	math80
1	1	english91
2	3	chinese99
3	3	math24
4	4	english64
   sno	爱好	grade
0	1	画画	math80
1	1	画画	english91
2	1	篮球	math80
3	1	篮球	english91
4	3	c足球	chinese99
5	3	c足球	math24
6	3	d画画	chinese99
7	3	d画画	math24

3.理解how的left、right、inner、outer的区别

在这里插入图片描述

4.如果出现非key的字段重名怎么办

五、数据合并concat

使用场景:批量合并相同格式的EXCEl、给DataFrame添加行、列

1.cancat语法

pandas.concat(objs,axis=0,join=‘outer’,ignore_index=False)
*objs:一个列表,内容可以是DataFrame或者series,也可以混合
*axis:默认是0代表行合并,1是列合并
*join:合并的时候索引的对齐方式,默认是outer join,也可以是inner join

DataFrame.append(other,ignore_index=False)
append只有按行合并,没有按列合并,相当于cancat 的简写形式
*other:单个dataframe、series、dict、列表
*ignore_index:是否忽略原来的数据索引

import pandas as pd
import warnings
warnings.filterwarnings('ignore')
df1=pd.DataFrame({'A':['A0','A1','A2','A3'],'B':['B0','B1','B2','B3'],'C':['C0','C1','C2','C3'],'D':['D0','D1','D2','D3'],'E':['E0','E1','E2','E3'],})
df1
df2=pd.DataFrame({'A':['A4','A5','A6','A7'],'B':['B0','B1','B2','B7'],'C':['C0','C1','C2','C7'],'D':['D0','D1','D2','D7'],'F':['f0','f1','F2','F3'],})
df2
#默认的concat,参数为axis=0,join=outer,ignore_index=False
df=pd.concat([df1,df2])
df
#过滤掉不匹配的列
dfa=pd.concat([df1,df2],ignore_index=True,join='inner')
dfa
#axis=1相当于添加新列
s1=pd.Series(list(range(4)),name='new')
pd.concat([df1,s1],axis=1)
#添加多列
s2=df1.apply(lambda x:x['A']+"_XX",axis=1)
s2.name='G'
pd.concat([df2,s1,s2],axis=1)
	A	B	C	D	E      
0	A0	B0	C0	D0	E0
1	A1	B1	C1	D1	E1
2	A2	B2	C2	D2	E2
3	A3	B3	C3	D3	E3
	A	B	C	D	F
0	A4	B0	C0	D0	f0
1	A5	B1	C1	D1	f1
2	A6	B2	C2	D2	F2
3	A7	B7	C7	D7	F3
A	B	C	D	E	F
0	A0	B0	C0	D0	E0	NaN
1	A1	B1	C1	D1	E1	NaN
2	A2	B2	C2	D2	E2	NaN
3	A3	B3	C3	D3	E3	NaN
0	A4	B0	C0	D0	NaN	f0
1	A5	B1	C1	D1	NaN	f1
2	A6	B2	C2	D2	NaN	F2
3	A7	B7	C7	D7	NaN	F3
	A	B	C	D	E	new
0	A0	B0	C0	D0	E0	0
1	A1	B1	C1	D1	E1	1
2	A2	B2	C2	D2	E2	2
3	A3	B3	C3	D3	E3	3

2.dataframe.append按行合并数据

df1=pd.DataFrame([[1,2],[3,4]],columns=list('AB'))
df1
df2=pd.DataFrame([[5,6],[7,8]],columns=list('AB'))
df2
df1.append(df2,ignore_index=True)
#一个空的df
df=pd.DataFrame(columns=['A'])
df
#低性能版本
for i in range(5):
    df=df.append({'A':i},ignore_index=True)
df
#性能较好版本
pd.concat([pd.DataFrame([i],columns=['A']) for i in range(5)],ignore_index=True)

六、分组统计groupby

1.groupby的含义

groupby:先对数据分组,然后在每个分组上应用聚合函数、转换函数
本次:
1.分组使用聚合函数做数据统计
2.遍历groupby的结果理解执行流程
3.多级索引

import pandas as pd
import numpy as np
df=pd.DataFrame({'A':['xiao1','xiao2','xiao1','xiao2','xiao2'],'B':['c','d','d','c','c'],'C':np.random.randn(5),'D':np.random.randn(5)})
df
#1、单个列groupby,查询所有数据列的统计
#A列变成了数据的索引列
#因为要统计sum,B列不是数字就被自动忽略了
df.groupby('A').sum()
#2、多个列groupby,查询所有数据列的统计,mean是求平均值
#(A,B)成对变成了二级索引
df.groupby(['A','B']).mean()
df.groupby(['A','B'],as_index=False).mean()#这就避免了(A,B)变成索引
#3、同时查看多钟数据统计,这使得列表变成了多级索引
df.groupby('A').agg([np.sum,np.mean,np.std])#np.std是标准差
#python中的agg函数通常用于调用groupby()函数之后,对数据做一些聚合操作,包括sum,min,max以及其他一些聚合函数
#4、查看单列的结果数据统计
#方法1:预过滤,性能更好
df.groupby('A')['C'].agg([np.sum,np.mean,np.std])
#方法2
df.groupby('A').agg([np.sum,np.mean,np.std])['C']
#不同列分别使用不同的聚合函数
df.groupby('A').agg({"C":np.sum,"D":np.mean})

2.遍历groupby的结果理解执行流程

for循环可以直接遍历每个group

#1、遍历单个列聚合的分组
g=df.groupby('A')
g
for name,group in g:
    print(name)
    print(group)
    print()
#可以获得单个分组的数据
g.get_group('xiao2')
#2、遍历多个列聚合的分组
b=df.groupby(['A','B'])
for name,group in b:
    print(name)
    print(group)
    print()
#上面的话那么是一个有2个元素的tuple,代表不同的列
b.get_group(('xiao1','c'))
#可以直接查询group后的某几列,生成series或者子Dataframe
b['C']
for name,group in b['C']:
    print(name)
    print(group)
    print(type(group))
    print()

3.多级索引

当groupby([‘A’,‘B’])时表会变成多级索引,所以需要对多级索引进行处理,以下代码有对series多维索引的处理,也有对dataframe多维索引的处理

import pandas as pd
import numpy as np
df=pd.DataFrame({'A':['xiao1','xiao2','xiao1','xiao2','xiao2','baidu','baidu'],'B':['20210101','20210101','20210103','20210104','20210105','20210105','20210101'],'C':np.random.randn(7),'D':np.random.randn(7)})
ser=df.groupby(['A','B'])['C'].mean()
ser#ser里是一个多维索引
ser.index
#unstack把二级索引变成列,A列变成竖着的表头,B列变成横着的表头
ser.unstack()
#删除二级索引
#ser.reset_index()
#有多层索引MultiIndex怎么筛选数据?
ser
ser.loc['xiao1']
#多层索引,可以用元组的形式筛选
ser.loc[('xiao1','20210101')]
ser.loc[:,'20210101']
#DataFrame的多层索引MultiIndex
df.head()
df.set_index(['A','B'],inplace=True)
df.index
#排序后性能会好很多
df.sort_index(inplace=True)
df
#***DataFrame有多层索引MultiIndex怎样筛选数据
#[重要知识]在选择数据时:
#1、元祖(key1,key2)代表筛选多层索引,其中key1是索引第一级,key2是第二级,比如key1=xiao1,key2=c
#2、列表[key1,key2]代表同一层的多个key,其中key1和key2是并列的同级索引,比如key1=xiao1,key2=baidu
df.loc['baidu']
df.loc[('baidu','20210101'),:]
df.loc[['xiao1','baidu'],:]
df.loc[(['xiao1','baidu'],'20210101'),:]
df.loc[(['xiao1','baidu'],'20210101'),'C']
df.loc[('baidu',['20210101','20210105']),:]
#slice(None)代表筛选这一索引的所有内容
df.loc[(slice(None),['20210101','20210103']),:]
#删除多维索引
df.reset_index()

4.groupby后的字符串合并拼接处理

import pandas as pd
import numpy as np
df=pd.DataFrame({'A':['xiao1','xiao1','xiao1','baidu','baidu','baidu','baidu'],'B':['a01','b1','c3','a4','b5','c5','d101'],'C':['a','a','a','a','a','a','a']})
data=df.groupby('A')['B'].apply(lambda x:x.str.cat()).reset_index()
data
data=df.groupby('A')['B'].apply(lambda x:x.str.cat(sep=':')).reset_index()
data
#相关数据如下,C列是后面加的
A	B
0	xiao1	a01
1	xiao1	b1
2	xiao1	c3
3	baidu	a4
4	baidu	b5
5	baidu	c5
6	baidu	d101
#运行结果
	A	B
0	baidu	a4b5c5d101
1	xiao1	a01b1c3
      A	        B
0	baidu	a4:b5:c5:d101
1	xiao1	a01:b1:c3

5.groupby.apply()

知识点:pandas的groupby遵从split、apply、combine模式:
这个split指的是groupby,apply是我们自己实现的函数,apply返回的结果有pandas进行combine得到结果
在这里插入图片描述
groupby.apply(function)
*function的第一个参数是dataframe
*function的返回结果,可以是datafr、series、单个值、甚至和输入dataframe完全没关系
本次实例演示:
1、怎样对数字列按照分组的归一化
2、怎么取每个分组的topN数据

实例1:怎么对数值列按分组的归一化?

将不同范围的数值列进行归一化,映射到[0,1]区间:
*更容易做数据横向对比,比如价格字段是几百到几千,增幅字段是0到几百
*归一化后,机器学习模型学的更快性能更好
归一化的公式:
在这里插入图片描述

import pandas as pd
import numpy as np
#构造用户的电影评分表,然后对其中一列归一化
ratings=pd.DataFrame({"userid":[1,1,1,1,1],"movieid":[110,111,112,221,902],"rating":[5,3,3,4,5],"timestamp":[978300760,978302109,978301968,978300275,978824291]})
ratings
#实现按照用户ID分组,然后对其中一列归一化
def ratings_norm(df):
    min_value=df["rating"].min()
    max_value=df["rating"].max()
    df["rating_norm"]=df["rating"].apply(
        lambda x: (x-min_value)/(max_value-min_value)
    )
    return df
ratings =ratings.groupby("userid").apply(ratings_norm)
ratings[ratings["userid"]==1].head()
#可以看到1这个用户,最低评分是3,我们将3分归一到0

提示:相关数据
在这里插入图片描述

实例2:怎么取每个分组的topn数据

获取2018年每个月份最高温度的2天数据

import pandas as pd
import numpy as np
import pandas as pd
import numpy as np
fpath=r"G:\360Downloads\myself\zuoye\groupby后字符串合并处理\tianqi.xlsx"
df=pd.read_excel(fpath)
df.head()
#替换℃
df.loc[:,"bwendu"]=df["bwendu"].str.replace("℃","").astype('int32')
df.loc[:,"ywendu"]=df["ywendu"].str.replace("℃","").astype('int32')
#新增一列为月份,这种方法只有月份没有年份
df["ymd"]=pd.to_datetime(df["ymd"])
df["month"]=df["ymd"].dt.month
#新增一列为月份的还一种方法
df["month2"]=df["ymd"].astype('str').str[:7]
df.head()
def getWenduTopN(df,topn):
    """这里的df是每个月份分组group的df"""
    return df.sort_values(by="bwendu")[["ymd","bwendu"]][-topn:]
df.groupby("month2").apply(getWenduTopN,2).head()

数据我只整两个月的

6.groupby的一些函数使用【统计函数】

知识点:pandas的groupby后的函数使用:

#使用月份和乡镇两列聚合后,两种使用sum求和函数的方法,结果完全不一样,agg这种所有的列都sum了,而第二种写法只针对数据列求和
df_group=df.groupby([df["date"].dt.month,"乡镇(街道)"]).agg({'sum'})
df_group=df.groupby([df["date"].dt.month,"乡镇(街道)"])["证件号码"].agg(pv=np.sum)
df_group=df.groupby([df["date"].dt.month,"乡镇(街道)"]).sum()
#这个函数相当于excel的count()计数函数
df_group=df.groupby([df["date"].dt.month,"乡镇(街道)"]).size()
#怎么对增加的计数列命名
df_group=df.groupby([df["date"].dt.month,"乡镇(街道)"])["证件号码"].agg(pv=np.size)
df_group=df.groupby([df["date"].dt.month,"乡镇(街道)"])["证件号码"].agg([("count","count")])
#这是新增多列的命名方式
df_group=df.groupby([df["date"].dt.month,"乡镇(街道)"])["证件号码"].agg([("count","count"),("size1","size")]).reset_index()

7.多级索引处理实例

实现表格按照列【‘XX机构编号’,‘月’,‘xx类别’, ‘结算xx’,‘险种xx’】进行求和汇总后,再将相关数据匹配上去

import pandas as pd
import numpy as np
import os
df=pd.read_excel(r"G:\360Downloads\myself\zuoye\2023\5月\2022初始数据.xlsx")
df.columns


df.info()
df['月']=pd.to_datetime(df['结算时间']).dt.month
df.head()

dff=df.groupby(['XX机构编号','月','xx类别', '结算xx','险种xx']).sum()
dff.to_excel(r"G:\360Downloads\myself\zuoye\2023\5月\b.xlsx")

dff=df.groupby(['XX机构编号','月','xx类别', '结算xx','险种xx']).size()
dff.to_excel(r"G:\360Downloads\myself\zuoye\2023\5月\c.xlsx")

#改良后的版本
dff=df.groupby(['XX机构编号','月','xx类别', '结算xx','险种xx']).sum().reset_index()
df2=df.groupby(['XX机构编号','月','xx类别', '结算xx','险种xx'])["证件号码"].agg(size=np.size).reset_index()

df2.info()
dff.info()

df3=pd.merge(df2,dff,on=['XX机构编号','月','xx类别', '结算xx','险种xx'],how='outer')
df3.info()

df.columns
df4=df[['机构编号', '机构名称']]
df4.info()
df4.drop_duplicates(subset=['机构编号'] ,keep="first",inplace=True)
df4.info()

df3.info()
df5=pd.merge(df3,df4,on='机构编号',how='left')
df5.info()
df5.to_excel(r"G:\360Downloads\myself\zuoye\2023\5月\b.xlsx")

#Pandas怎样实现Excel的vlookup并且在指定列后面输出
#实现将机构名称放在机构编码后面
# 将columns变成python的列表形式
new_columns = df5.columns.to_list()
new_columns

# 按逆序insert,会将"机构名称"放到"机构编号"的后面
for name in ['机构名称'][::-1]:
    new_columns.remove(name)
    new_columns.insert(new_columns.index("机构编号")+1, name)
    df_merge = df5.reindex(columns=new_columns)
df_merge.head()

七、pandas数据转换函数

数据转换的大概理解就是将某列英文(或其他东西)按照某种对应规则把它转换成汉语

1.pandas 的数据转换函数

有map、apply、applymap
1、map:只用于series,实现每个值到值的映射
2、apply:用于series实现对每个值的处理,也可用于dataframe实现某个轴的series的处理
3、applymap:只能用于Dataframe,用于处理dataframe的每个元素

2.map用于series值的转换

实例:将英语公司名称转换成中文
series.map(dict)orseries.map(function)
代码如下(示例):

import pandas as pd
import numpy as np
fpath=r"G:\360Downloads\myself\zuoye\groupby后字符串合并处理\tianqi.xlsx"
df=pd.read_excel(fpath)
df.head()
#公司列去重,查看有哪些数据
df["公司"].unique()
#公司名称都是小写
dict_company_names={
    "bidu":"百度",
    "baba":"阿里",
    "iq":"爱奇艺",
    "jd":"京东"
}
#方法1,lower是把字母都变成小写
df["gongsi"]=df["公司"].str.lower().map(dict_company_names)
df
#方法2,series.map(function)
#function的参数是series的每个元素的值
df["gs"]=df["公司"].map(lambda x: dict_company_names[x.lower()])
df

在这里插入图片描述

3.apply用于series和dataframe的转换

*series.apply(function),函数参数是每个值
*dataframe.apply(function)函数参数是series

代码如下(示例):

df["gs"]=df["公司"].apply(lambda x: dict_company_names[x.lower()])
#DataFrame.apply(function)function的参数是对应轴的series
df["gs3"]=df.apply(
    lambda x: dict_company_names[x["公司"].lower()],
    axis=1
)
#ps:apply是在df这个DataFrame上调用
#lambda x的x是一个serise,因为指定了axis=1,所以series的key是列名,可以用x["公司"]获取
df.head()

4.applymap用于dataframe所有值的转换

代码如下(示例):

sub_df=df[["收盘","开盘"]]
sub_df.head()
#将这些数字取整数,应用于所有元素
sub_df.applymap(lambda x: int(x))
#直接修改原df的这几行
df.loc[:,["收盘","开盘"]]=sub_df.applymap(lambda x: int(x))
df.head()

八、pandas的stack和pivot实现数据透视

提示:将列式数据变成二维交叉形式,便于分析,叫做重塑或透视
1.经过统计得到多维度指标数据
2.使用unstack实现数据二维透视
3.使用pivot简化透视
4.stack、unctack、pivot的语法
应用场景:
在这里插入图片描述

import pandas as pd
import numpy  as np
import matplotlib.pyplot as plt
fpath=r"G:\360Downloads\myself\zuoye\try\月份grouby.xlsx"
df=pd.read_excel(fpath)
df=df[["证件号码","乡镇(街道)","村(社区)","开始时间","总额","自费金额"]]
df.head()
df["date"]=pd.to_datetime(df["开始时间"])
#按月份统计乡镇出现次数
df_group=df.groupby([df["date"].dt.month,"乡镇(街道)"])["证件号码"].agg([("count","count")])
df_group
#对于有这种多重索引的格式,想查看按月份,不同乡镇的出现次数趋势是没办法实现的
#需要将数据变换成每个评分是一列才可以实现

#2.使用unstack实现数据二维透视
#目的是想要画图对比按照月份的不同评分的数量趋势
df_stack=df_group.unstack()#这样的表就把二层索引变成好画图的表
df_stack
df_stack.plot()
#unstack和stack是互逆的操作
df_stack.stack().head()

#3.使用pivot简化透视
#pivot方法相当于对df使用set_index创建分层索引,然后调用unstack
df_group.head(20)
df_reset=df_group.reset_index()
df_reset.head(20)
df_pivot=df_reset.pivot("date","乡镇(街道)","count")
df_pivot.head()
df_pivot.plot()

#4.stack、unstack、pivot的语法
#satck:DataFrame。stack(level=-1,dropna=True),将column变成index,类似把横放的书籍变成竖放
#level=-1代表多层索引的最内层,可以通过==0,1,2,指定多层索引的对应层

九、快速实现周月季度的日期聚合统计DatatimeIndex

1.介绍

链接:https://www.bilibili.com/video/BV1eJ411Q7Vd?spm_id_from=333.337.search-card.all.click
Pandas日期处理的作用:将2018-01-01、1/1/2018等多种日期格式映射成统一的格式对象,在该对象上提供强大的功能支持
几个概念:
a。pd.to_datetime:pandas的一个函数,能将字符串、列表、series变成日期形式
b。Timestamp:pandas表示日期的对象形式
c。DatetimeIndex:pandas表示日期的对象列表形式
其中:
DatetimeIndex是Timestamp的列表形式
pd.to_datetime对单个日期字符串处理会得到Timestamp
pd.to_datetime对日期字符串列表处理会得到DatetimeIndex
在这里插入图片描述
Timestamp、DatetimeIndex支持大量的属性可以获取日期分量:
http://pandas.pydata.org/pandas-docs/stable/user_guide/timeseries.html#time-date-components

2.代码介绍

可以试用于的场景:已有每天一条数据的表格(比如天气表、股票表),怎么统计每周、每月、每季度的最高温度呢?

代码如下(示例):

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

#1.读取天气数据
df=pd.read_excel(r"G:\360Downloads\myself\zuoye\code\10年天气数据.xlsx")
df.head()
df.loc[:,"最高温"]=df["最高温"].str.replace("°","").astype('int32')
df.loc[:,"最低温"]=df["最低温"].str.replace("°","").astype('int32')
#df.info()
df.head(20)
df.loc[:,"日期"]=df["日期"].str[0:10]
df.head()
#只需要2018年的数据
condition=df["日期"].str.startswith("2018")
df=df[condition]
df.info()

#2.将日期列转换成pandas的日期
df.set_index(pd.to_datetime(df["日期"]),inplace=True)
df.head()
df.index
#DatetimeIndex是Timestamp的列表形式
df.index[0]

#3.方便对DatetimeIndex进行查询
#如果不是DatetimeIndex的话,没办法用这样的前缀筛选,需要上面的startswith
#筛选固定的某一天
df.loc['2018-01-05']
#日期区间
df.loc['2018-01-05':'2018-01-15']
#按月份前缀筛选
df.loc['2018-03'].head(10)
#按月份前缀筛选
df.loc['2018-03':'2018-05'].index
#按年份前缀筛选
df.loc['2018'].head()

#4.方面的获取周、月、季度
df.index.week
df.index.month
df.index.quarter

#5.统计每周、每月、每个季度的最高温度
df.groupby(df.index.week)["最高温"].max().head(20)
df.groupby(df.index.week)["最高温"].max().plot()

df.groupby(df.index.month)["最高温"].max().head(12)
df.groupby(df.index.month)["最高温"].max().plot()

df.groupby(df.index.quarter)["最高温"].max()
df.groupby(df.index.quarter)["最高温"].max().plot()

3.怎么处理日期索引的缺失

可以试用于的场景:按日期统计的数据,缺失了某天,导致数据不全怎么补充日期?
可以用两种方法实现:
1、DataFrame.reindex,调整dataframe的索引以适应新的索引
2、DataFrame.resample,可以对时间序列重采样,支持补充缺失值
resample的采样规则参数:http://pandas.pydata.org/pandas-docs/stable/user_guide/timeseries.html#offset-aliases

代码如下(示例):

from textwrap import fill
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

df=pd.DataFrame({"pdate":["2019-01-01","2019-01-02","2019-01-04","2019-01-05"],
                 "pv":[100,200,400,500],
                 "uv":[10,20,40,50]})
df

df.set_index("pdate").plot()
#这样打出来的图像有个标记,缺了13号数据

#方法1:使用pandas.reindex方法
#1。将df的索引标称日期索引
df_date=df.set_index("pdate")
df_date
df_date.index#索引还是dtype='object'
#将df索引设置为日期索引
df_date=df_date.set_index(pd.to_datetime(df_date.index))
df_date.index#索引还是dtype='datetime64[ns]'
#2。使用pandas.reindex填充缺失的索引
#生成完整的日期序列
pdates=pd.date_range(start="2019-01-01",end="2019-01-05")
pdates
df_date_new=df_date.reindex(pdates, fill_value=0)
df_date_new.plot()

#方法2:使用pandas。resample方法
#resample的含义:改变数据的时间频率,比如把天数据变成月数据(由小变大),或者把小时数据变成分钟级别(由大变小)
#resample语法:DataFrame/Series.resample(arguments).(aggregate function)
#resample的采样规则参数:http://pandas.pydata.org/pandas-docs/stable/user_guide/timeseries.html#offset-aliases
df_new2=df.set_index(pd.to_datetime(df["pdate"])).drop("pdate",axis=1)
df_new2
#由于采样会让区间变成一个值,所以需要制定mean等采样值的设定方法
df_new2=df_new2.resample("D").mean().fillna(0)
df_new2
#D是天,2D是2
df_new2.resample("2D").mean()

4.pd.to_datetime()函数

代码如下(示例):

import pandas as pd
import numpy as np
df=pd.read_excel(r"G:\360Downloads\myself\zuoye\2023\4月\3\资金到人到户发放导入模板(1).xlsx")
df.info()
df['发放'] = pd.to_datetime(df['发放时间'], errors='coerce')
#errors='coerce'这个参数让日期错误的,变为空
df.to_excel(r"G:\360Downloads\myself\zuoye\2023\4月\3\1.xlsx")

十、图相关

1.通过折线图发现产品流量问题

折线图是随着时间而变化的连续数据,展现时间间隔相等的时候的数据趋势

实例数据来自kaggle网站地址:https://www.kaggle.com/datasets/aerodinamicc/ecommerce-website-funnel-analysis
总共有四个页面数据:
1.home_page_table.csv ,首页用户访问数据
2.payment_confirmation_table.csv 支付成功页面用户访问数据
3.payment_page_table.csv 支付信息页面用户访问数据
4.search_page_table.csv搜索页面用户访问数据
5.user_table.csv 用户信息表
目标:绘制转化率的折线图,查询是否有异常情况

代码

import pandas as pd
import numpy as np
import pyecharts.options as opts
from pyecharts.charts import Line

#1、读取数据
df_home_page=pd.read_csv(r"D:\搜狗高速下载\archive\home_page_table.csv")
df_search_page=pd.read_csv(r"D:\搜狗高速下载\archive\search_page_table.csv")
df_payment_page=pd.read_csv(r"D:\搜狗高速下载\archive\payment_page_table.csv")
df_payment_confirmation_page=pd.read_csv(r"D:\搜狗高速下载\archive\payment_confirmation_table.csv")
df_user_table=pd.read_csv(r"D:\搜狗高速下载\archive\user_table.csv")
#查看每张表的构造,页面表就是用户id和访问页面名称
#用户表是id加时间、设备、性别
df_user_table.head()
df_home_page.head()
df_search_page.head()

#2、关联5个数据表为一个大表
df_merge=df_user_table
for df_inter in [df_home_page,df_search_page,df_payment_page,df_payment_confirmation_page]:
    #每次循环都在df_merge中添加新列
    df_merge =pd.merge(df_merge,df_inter,on="user_id",how="left")
df_merge.head()
#对列新命名
df_merge.columns=["user_id","date","device","sex","home_page","search_page","payment_page","confirmation_page"]
df_merge.head()
#对时间列进行处理
df_merge["date"]=pd.to_datetime(df_merge["date"])
df_merge.head()

#3、展现每个页面整体的PV曲线
df_data=(
    df_merge.groupby("date").agg(
        home_page=("home_page", lambda x:x.dropna().size),
        search_page=("search_page", lambda x:x.dropna().size),
        payment_page=("payment_page",lambda x:x.dropna().size),
        confirmation_page=("confirmation_page",lambda x:x.dropna().size)

    )
)
df_data.head()
#绘制折线图
c =(
    Line()
    .add_xaxis(df_data.index.to_list())
    .add_yaxis("home_page",df_data["home_page"].to_list())
    .add_yaxis("search_page",df_data["search_page"].to_list())
    .add_yaxis("payment_page",df_data["payment_page"].to_list())
    .add_yaxis("confirmation_page",df_data["confirmation_page"].to_list())
    .set_global_opts(title_opts=opts.TitleOpts(title="整体PV折线"))   
)
c.render_notebook()

#4、查看分设备的PV曲线
df_data = (
    df_merge.groupby(["date","device"])["search_page"].agg(
        search_page=lambda x:x.dropna().size
    ).unstack()
)
df_data.head()
c=(
    Line()
    .add_xaxis(df_data.index.to_list())
    .add_yaxis("desktop",df_data[("search_page","Desktop")].to_list())
    .add_yaxis("mobile",df_data[("search_page","Mobile")].to_list())
    .set_global_opts(title_opts=opts.TitleOpts(title="搜索页面PV"))
    
)
c.render_notebook()

分析

1.引入的数据表长啥样
在这里插入图片描述
2.5个表关联成大表后,更改列名后:
在这里插入图片描述
3.1对数据进行处理后,得出每天访问各个页面的人数
在这里插入图片描述
3.2整体PV图,可以看出搜索页数据有明显的波动
在这里插入图片描述
4.对搜索页的设备端进行统计,进行详细分析试图找出问题
在这里插入图片描述
在这里插入图片描述
3月1号手机端搜索量下降不正常


总结

提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值