王秀芳 發表於 2026-1-7 09:21:29

Pandas基础使用指南之排序、字符串日期处理和文件合并拆分技巧

<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li><a href="#_label0">一、排序</a></li><ul class="second_class_ul"><li><a href="#_lab2_0_0">1.1 对Series排序</a></li><li><a href="#_lab2_0_1">1.2 对DataFrame排序</a></li></ul><li><a href="#_label1">二、字符串和日期处理</a></li><ul class="second_class_ul"></ul><li><a href="#_label2">三、DataFrame的连接</a></li><ul class="second_class_ul"></ul><li><a href="#_label3">四、EXCEL表格批量合并和拆分</a></li><ul class="second_class_ul"><li><a href="#_lab2_3_2">4.1 批量进行表格合并</a></li><li><a href="#_lab2_3_3">4.2 批量进行表格拆分</a></li></ul></ul></div><p>之前我们已经介绍了 pandas的基础使用用法,这一期我们来看看这个包其他有意思的方法</p>
<p class="maodian"><a name="_label0"></a></p><h2>一、排序</h2>
<p class="maodian"><a name="_lab2_0_0"></a></p><h3>1.1 对Series排序</h3>
<p>对<code>Series</code>的排序,主要是两个参数,一个是<code>ascending</code>,代表是否升序排列,另一个就是很熟悉的<code>inplace</code> 了</p>
<div class="jb51code"><pre class="brush:py;">sr = pd.Series()
sr.sort_values(ascending=False,inplace=True) # 降序排序,同时替换原有DataFrame
print(sr)
</pre></div>
<p>输出的结果为,注意排序后<code>index</code>的顺序也会跟着变:</p>
<blockquote><p>2 &nbsp; &nbsp;8<br />4 &nbsp; &nbsp;5<br />3 &nbsp; &nbsp;4<br />1 &nbsp; &nbsp;3<br />0 &nbsp; &nbsp;2<br />dtype: int64</p></blockquote>
<p class="maodian"><a name="_lab2_0_1"></a></p><h3>1.2 对DataFrame排序</h3>
<p>由于<code>DataFrame</code>是二维的,因此排序时多了一个参数<code>by</code>,表示按照哪一列进行排序,同时<code>ascending</code>也支持布尔数组,实现多条件的排序,如下:</p>
<div class="jb51code"><pre class="brush:py;">df = pd.DataFrame({"A":["B","A","B","B","A"],
                  "B":,
                  "C":})
# 单条件排序
df.sort_values(by="B",ascending=True,inplace=True)
print(df)
</pre></div>
<p>单条件的排序结果为:</p>
<blockquote><p>&nbsp; &nbsp; A &nbsp;B &nbsp; C<br />0 &nbsp;B &nbsp;2 &nbsp;11<br />1 &nbsp;A &nbsp;3 &nbsp; 2<br />3 &nbsp;B &nbsp;4 &nbsp; 4<br />4 &nbsp;A &nbsp;5 &nbsp; 5<br />2 &nbsp;B &nbsp;8 &nbsp; 7</p></blockquote>
<p>而对于多条件排序,<code>by</code>和<code>ascending</code>一一对应,代表应该是升序还是降序</p>
<div class="jb51code"><pre class="brush:py;"># 多条件排序
df.sort_values(by=["A","B"],ascending=,inplace=True)
print(df)
</pre></div>
<p>多条件排序输出结果如下,首先按照A列降序排序,然后按照B列升序排序,所以有一个主次的关系:</p>
<blockquote><p>&nbsp; &nbsp;A &nbsp;B &nbsp; C<br />0 &nbsp;B &nbsp;2 &nbsp;11<br />3 &nbsp;B &nbsp;4 &nbsp; 4<br />2 &nbsp;B &nbsp;8 &nbsp; 7<br />1 &nbsp;A &nbsp;3 &nbsp; 2<br />4 &nbsp;A &nbsp;5 &nbsp; 5</p></blockquote>
<p class="maodian"><a name="_label1"></a></p><h2>二、字符串和日期处理</h2>
<p>对于字符串的处理,我们一般都使用<code>str</code>进行,而对于日期,我们用<code>dt</code>,直接通过底下的代码我们来看</p>
<div class="jb51code"><pre class="brush:py;">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
# 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)
</pre></div>
<p>输出如下,我们一个一个做分析,首先我们定义了一个<code>DataFrame</code>,可以发现初始都是字符串,因此输出为<code>object</code>,然后我们通过<code>to_datetime</code>将其改成了标准的日期格式,因此输出为<code>datetime64</code>,同样我们也可以通过<code>dt.strftime</code>将其转换为字符串格式,对于字符串格式,我们可以使用<code>str</code>下的若干方法进行处理,上述演示中只是将&ldquo;分&rdquo;这个字删除,并转换为整型:</p>
<blockquote><p>姓名 &nbsp; &nbsp; &nbsp;object<br />出生日期 &nbsp; &nbsp;object<br />分数 &nbsp; &nbsp; &nbsp;object<br />dtype: object<br />==============================<br />datetime64<br />object<br />&nbsp; &nbsp;姓名 &nbsp; &nbsp; &nbsp; &nbsp;出生日期 &nbsp;分数<br />0 &nbsp;张三 &nbsp;2000-01-01 &nbsp;90<br />1 &nbsp;李四 &nbsp;2001-02-02 &nbsp;29<br />2 &nbsp;王五 &nbsp;2002-03-03 &nbsp;78<br />3 &nbsp;赵六 &nbsp;2003-04-04 &nbsp;46<br />4 &nbsp;王二 &nbsp;2004-05-05 &nbsp;57</p></blockquote>
<p>同时<code>pandas</code>严格约定<code>str</code>只服务于字符串,如果对其他格式使用,则会报错,对于字符串的处理,还有一个很强大的工具就是正则表达式,我们同样可以使用正则表达式进行处理,但是注意使用<code>regex=True</code>告诉程序这个是正则表达式:</p>
<div class="jb51code"><pre class="brush:py;"># 常规复杂的三步替换
df["出生日期"] = df["出生日期"].str.replace("年","").str.replace("月","").str.replace("日","")
# 正则表达式替换
df["出生日期"] = df["出生日期"].str.replace("[年月日]","",regex=True)
</pre></div>
<p class="maodian"><a name="_label2"></a></p><h2>三、DataFrame的连接</h2>
<p>如果需要做DataFrame的连接,我们常常使用<code>concat</code>方法,其重要的三个参数分别是</p>
<ul><li><code>axis=0</code> 代表按行连接,否则是按列连接</li><li><code>ignore_index=True</code> 表示重新生成一个新的索引,否则保留原始索引</li><li><code>join=&quot;outer&quot;</code> 表示保留所有非重复字段,<code>join=&quot;inner&quot;</code>则表示只保留重合字段</li></ul>
<div class="jb51code"><pre class="brush:py;">df1 = pd.DataFrame({"A":,
                  "B":})
df2 = pd.DataFrame({"B":,
                  "F":})
print(pd.concat(,axis=1))
print(pd.concat(,axis=0,ignore_index=True,join="outer"))
</pre></div>
<p>输出结果为:</p>
<blockquote><p>&nbsp; &nbsp;A &nbsp;B &nbsp;B &nbsp; F<br />0 &nbsp;1 &nbsp;6 &nbsp;4 &nbsp; 9<br />1 &nbsp;2 &nbsp;7 &nbsp;5 &nbsp;10<br />2 &nbsp;3 &nbsp;8 &nbsp;6 &nbsp;11<br />&nbsp; &nbsp; &nbsp;A &nbsp;B &nbsp; &nbsp; F<br />0 &nbsp;1.0 &nbsp;6 &nbsp; NaN<br />1 &nbsp;2.0 &nbsp;7 &nbsp; NaN<br />2 &nbsp;3.0 &nbsp;8 &nbsp; NaN<br />3 &nbsp;NaN &nbsp;4 &nbsp; 9.0<br />4 &nbsp;NaN &nbsp;5 &nbsp;10.0<br />5 &nbsp;NaN &nbsp;6 &nbsp;11.0</p></blockquote>
<p>在输出中,如果 <code>ignore_index=False</code> ,左侧就是原始索引 ,而如果使用<code>join=&quot;inner&quot;</code>则只会保留重合的B列</p>
<p>同时<code>Concat</code>还支持<code>DataFrame</code> 与<code>Series</code>的混合拼接,例如:</p>
<div class="jb51code"><pre class="brush:py;">sr1 = pd.Series(,name="sr1")
sr2 = pd.Series(,name="sr2")

print(pd.concat(,axis=1)) # 混合拼接
</pre></div>
<p>输出结果为:</p>
<blockquote><p>&nbsp; &nbsp;sr1 &nbsp;A &nbsp;B &nbsp;B &nbsp; F &nbsp;sr2<br />0 &nbsp; &nbsp;1 &nbsp;1 &nbsp;6 &nbsp;4 &nbsp; 9 &nbsp; &nbsp;6<br />1 &nbsp; &nbsp;2 &nbsp;2 &nbsp;7 &nbsp;5 &nbsp;10 &nbsp; &nbsp;7<br />2 &nbsp; &nbsp;3 &nbsp;3 &nbsp;8 &nbsp;6 &nbsp;11 &nbsp; &nbsp;8</p></blockquote>
<p class="maodian"><a name="_label3"></a></p><h2>四、EXCEL表格批量合并和拆分</h2>
<p class="maodian"><a name="_lab2_3_2"></a></p><h3>4.1 批量进行表格合并</h3>
<p>之前我们已经学习了那么多的<code>pandas</code>使用技巧,那么接下来我们就看看上面讲到的比如<code>Concat</code>在实际过程中有什么用吧,比如我们先看一下批量的合并,既然要合并,不过就是<code>DataFrame</code>的拼接,在某个文件夹下有若干个xlsx文件,我们需要合并到一张表里,这些子表的表头都是相同的:</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202601/2026010709200412.png" /></p>
<p>那么我们通过下面的程序进行合并,首先获取文件夹下所有的xlsx文件,然后读取<code>DataFrame</code>,紧接着添加一个标识列,代表从哪个数据表中拿到的,最后合并并保存,在这里<code>Concat</code>就起到了将各个<code>DataFrame</code>合并在一起的功能</p>
<div class="jb51code"><pre class="brush:py;">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(".") # 提取子文件的id作为新的一列
      df_lists.append(df) # 将当前子文件的DataFrame添加到列表中
# 使用Concat合并所有子文件的DataFrame
pd.concat(df_lists,axis=0).to_excel(file_to_save,index=False)
</pre></div>
<p>最后输出的文件中,就会多出我们新增的一列<code>son_id</code>,整个的处理非常迅速。</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202601/2026010709200448.png" /></p>
<p class="maodian"><a name="_lab2_3_3"></a></p><h3>4.2 批量进行表格拆分</h3>
<p>既然已经讲了合并,我们顺手也来看看拆分,我们的拆分需求是将表格平均分到若干个表里,在下面的程序中,我通过<code>son_file_num</code> 定义了要拆分的个数,通过考虑了除不尽的情况,然后依次按索引取值,放到每个表中</p>
<div class="jb51code"><pre class="brush:py;">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 // son_file_num # 每个子文件的数据条数
if df.shape % 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 # 这里的end是不包含在切片中的,所以不需要-1
    df_son.to_excel(f"{save_path}\{file_path.split('.')}_{i}.xlsx",index=False)
</pre></div>
<p>命令行输出了我们的一些调试信息,可想而知,会按152:152:152:150 的比例分配数据,实现拆分</p>
<blockquote><p>&nbsp; &nbsp; &nbsp; &nbsp; 出库日期 &nbsp; &nbsp; &nbsp; 产品经理 &nbsp;产品类别 &nbsp;地区 安全等级 &nbsp;销售额(元) &nbsp;销售数量 &nbsp;客户评分<br />0 2023-06-01 &nbsp; &nbsp; &nbsp;Jerry &nbsp;电子产品 &nbsp;西南 &nbsp; &nbsp;C &nbsp;3789.6 &nbsp; &nbsp;12 &nbsp; 5.0<br />1 2023-06-02 &nbsp; &nbsp; &nbsp; Cary &nbsp; &nbsp;服装 &nbsp;华东 &nbsp; &nbsp;A &nbsp;2345.3 &nbsp; &nbsp;14 &nbsp; 5.0<br />2 2023-06-03 &nbsp;Bob-Smith &nbsp;家居用品 &nbsp;西北 &nbsp; &nbsp;D &nbsp; 567.8 &nbsp; &nbsp; 7 &nbsp; 3.7<br />(606, 8)</p></blockquote>
頁: [1]
查看完整版本: Pandas基础使用指南之排序、字符串日期处理和文件合并拆分技巧