之前我们已经介绍了 pandas的基础使用用法,这一期我们来看看这个包其他有意思的方法
一、排序
1.1 对series排序
对series的排序,主要是两个参数,一个是ascending,代表是否升序排列,另一个就是很熟悉的inplace 了
sr = pd.series([2,3,8,4,5]) sr.sort_values(ascending=false,inplace=true) # 降序排序,同时替换原有dataframe print(sr)
输出的结果为,注意排序后index的顺序也会跟着变:
2 8
4 5
3 4
1 3
0 2
dtype: int64
1.2 对dataframe排序
由于dataframe是二维的,因此排序时多了一个参数by,表示按照哪一列进行排序,同时ascending也支持布尔数组,实现多条件的排序,如下:
df = pd.dataframe({"a":["b","a","b","b","a"],
"b":[2,3,8,4,5],
"c":[11,2,7,4,5]})
# 单条件排序
df.sort_values(by="b",ascending=true,inplace=true)
print(df)
单条件的排序结果为:
a b c
0 b 2 11
1 a 3 2
3 b 4 4
4 a 5 5
2 b 8 7
而对于多条件排序,by和ascending一一对应,代表应该是升序还是降序
# 多条件排序 df.sort_values(by=["a","b"],ascending=[false,true],inplace=true) print(df)
多条件排序输出结果如下,首先按照a列降序排序,然后按照b列升序排序,所以有一个主次的关系:
a b c
0 b 2 11
3 b 4 4
2 b 8 7
1 a 3 2
4 a 5 5
二、字符串和日期处理
对于字符串的处理,我们一般都使用str进行,而对于日期,我们用dt,直接通过底下的代码我们来看
df = pd.dataframe({"姓名":["张三","李四","王五","赵六","王二"],
"出生日期":["2000-01-01","2001-02-02","2002-03-03","2003-04-04","2004-05-05"],
"分数":["90分","29分","78分","46分","57分"]})
print(df.dtypes)
print("="*30)
df["出生日期"] = pd.to_datetime(df["出生日期"]) # 转换为日期类型
print(df["出生日期"].dtype) # datetime64[ns]
# df["出生日期"] = df["出生日期"].str.replace("1","") # 错误用法,str只能为字符串服务
df["出生日期"] = df["出生日期"].dt.strftime("%y-%m-%d") # 转换为字符串类型
print(df["出生日期"].dtype) # object
df["分数"] = df["分数"].str.replace("分","").astype(int) # 转换为整数类型
print(df)
输出如下,我们一个一个做分析,首先我们定义了一个dataframe,可以发现初始都是字符串,因此输出为object,然后我们通过to_datetime将其改成了标准的日期格式,因此输出为datetime64[ns],同样我们也可以通过dt.strftime将其转换为字符串格式,对于字符串格式,我们可以使用str下的若干方法进行处理,上述演示中只是将“分”这个字删除,并转换为整型:
姓名 object
出生日期 object
分数 object
dtype: object
==============================
datetime64[ns]
object
姓名 出生日期 分数
0 张三 2000-01-01 90
1 李四 2001-02-02 29
2 王五 2002-03-03 78
3 赵六 2003-04-04 46
4 王二 2004-05-05 57
同时pandas严格约定str只服务于字符串,如果对其他格式使用,则会报错,对于字符串的处理,还有一个很强大的工具就是正则表达式,我们同样可以使用正则表达式进行处理,但是注意使用regex=true告诉程序这个是正则表达式:
# 常规复杂的三步替换
df["出生日期"] = df["出生日期"].str.replace("年","").str.replace("月","").str.replace("日","")
# 正则表达式替换
df["出生日期"] = df["出生日期"].str.replace("[年月日]","",regex=true)
三、dataframe的连接
如果需要做dataframe的连接,我们常常使用concat方法,其重要的三个参数分别是
axis=0代表按行连接,否则是按列连接ignore_index=true表示重新生成一个新的索引,否则保留原始索引join="outer"表示保留所有非重复字段,join="inner"则表示只保留重合字段
df1 = pd.dataframe({"a":[1,2,3],
"b":[6,7,8]})
df2 = pd.dataframe({"b":[4,5,6],
"f":[9,10,11]})
print(pd.concat([df1,df2],axis=1))
print(pd.concat([df1,df2],axis=0,ignore_index=true,join="outer"))
输出结果为:
a b b f
0 1 6 4 9
1 2 7 5 10
2 3 8 6 11
a b f
0 1.0 6 nan
1 2.0 7 nan
2 3.0 8 nan
3 nan 4 9.0
4 nan 5 10.0
5 nan 6 11.0
在输出中,如果 ignore_index=false ,左侧就是原始索引 [0,1,2,0,1,2],而如果使用join="inner"则只会保留重合的b列
同时concat还支持dataframe 与series的混合拼接,例如:
sr1 = pd.series([1,2,3],name="sr1") sr2 = pd.series([6,7,8,],name="sr2") print(pd.concat([sr1,df1,df2,sr2],axis=1)) # 混合拼接
输出结果为:
sr1 a b b f sr2
0 1 1 6 4 9 6
1 2 2 7 5 10 7
2 3 3 8 6 11 8
四、excel表格批量合并和拆分
4.1 批量进行表格合并
之前我们已经学习了那么多的pandas使用技巧,那么接下来我们就看看上面讲到的比如concat在实际过程中有什么用吧,比如我们先看一下批量的合并,既然要合并,不过就是dataframe的拼接,在某个文件夹下有若干个xlsx文件,我们需要合并到一张表里,这些子表的表头都是相同的:

那么我们通过下面的程序进行合并,首先获取文件夹下所有的xlsx文件,然后读取dataframe,紧接着添加一个标识列,代表从哪个数据表中拿到的,最后合并并保存,在这里concat就起到了将各个dataframe合并在一起的功能
son_file_path = r"c:\users\22330\desktop\进行中\子文件"
file_to_save = r"c:\users\22330\desktop\进行中\data_combine.xlsx"
df_lists = [] # 用于存储每个子文件的dataframe
for item in os.listdir(son_file_path):
if item.endswith(".xlsx"):
file_path = os.path.join(son_file_path,item)
df = pd.read_excel(file_path)
df["son_id"] = item.split(".")[0] # 提取子文件的id作为新的一列
df_lists.append(df) # 将当前子文件的dataframe添加到列表中
# 使用concat合并所有子文件的dataframe
pd.concat(df_lists,axis=0).to_excel(file_to_save,index=false)
最后输出的文件中,就会多出我们新增的一列son_id,整个的处理非常迅速。

4.2 批量进行表格拆分
既然已经讲了合并,我们顺手也来看看拆分,我们的拆分需求是将表格平均分到若干个表里,在下面的程序中,我通过son_file_num 定义了要拆分的个数,通过考虑了除不尽的情况,然后依次按索引取值,放到每个表中
import pandas as pd
import os
file_path = r"c:\users\22330\desktop\进行中\data.xlsx"
save_path = r"c:\users\22330\desktop\进行中\子文件"
if not os.path.exists(save_path): # 如果子文件目录不存在,就创建一个
os.mkdir(save_path)
df = pd.read_excel(file_path)
print(df.head(3)) # 查看前3行数据
print(df.shape) # 查看数据条数和特征数
son_file_num = 4
son_file_size = df.shape[0] // son_file_num # 每个子文件的数据条数
if df.shape[0] % son_file_num != 0: # 如果数据条数不能被子文件数整除,需要额外增加一条数据
son_file_size += 1
for i in range(son_file_num):
start = i * son_file_size
end = start + son_file_size
df_son = df.iloc[start:end] # 这里的end是不包含在切片中的,所以不需要-1
df_son.to_excel(f"{save_path}\{file_path.split('.')[1]}_{i}.xlsx",index=false)
命令行输出了我们的一些调试信息,可想而知,会按152:152:152:150 的比例分配数据,实现拆分
出库日期 产品经理 产品类别 地区 安全等级 销售额(元) 销售数量 客户评分
0 2023-06-01 jerry 电子产品 西南 c 3789.6 12 5.0
1 2023-06-02 cary 服装 华东 a 2345.3 14 5.0
2 2023-06-03 bob-smith 家居用品 西北 d 567.8 7 3.7
(606, 8)
到此这篇关于pandas基础使用指南之排序、字符串日期处理和文件合并拆分技巧的文章就介绍到这了,更多相关python pandas使用内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论