Pandas實例|藥品發放匯總與excel表數據回填

      網友投稿 652 2022-05-30

      需求

      有一個衛生院需要統計一下每個村扶貧藥品發放的數據。

      數據形式是在一個文件夾下,每個村的數據都存儲在一個獨立的excel文件中,需要將每個村的數據進行匯總,匯總形式如下:

      數據處理流程

      首先讀取該文件夾下的其中一個文件進行測試:

      from pathlib import Path import pandas as pd for name in Path(r"F:\jupyter\test\藥品數據匯總\基礎表").glob("[!~]*.xls*"): filename = str(name.absolute()) df = pd.read_excel(filename, sheet_name="基礎表") break df.head(10)

      1

      2

      3

      4

      5

      6

      7

      8

      我們需要將指定的列向下填充缺失值用于分組聚合,如果直接調用datafream的fillna方法會將整個表所有的列都填充,官方文檔對該方法并沒有出一個只填充指定列的參數。

      所以我采用以下方法對指定的列進行填充:

      group_columns = ["序號", "姓名", "年齡", "身份證號碼", "家庭住址"] for c in group_columns: df[c].ffill(inplace=True) df.head()

      1

      2

      3

      4

      注意:ffill方法等價于fillna(method=‘ffill’)

      序號和年齡列由于一開始存在缺失值,導致轉換成浮點數類型,現在已經填充后,我們可以將其轉換回來:

      df.序號 = df.序號.astype("int16") df.年齡 = df.年齡.astype("int16")

      Pandas實例|藥品發放匯總與excel表數據回填

      1

      2

      注意:int16表示2字節的整數,這么寫是考慮到2字節的整數足夠裝的下年齡,可以節約一點內存,速度也會更快。

      根據結果要求,計算一些輔助列:

      df.eval("金額匯總=數量*單價", inplace=True) df.藥品 = df.藥品+df.數量.astype(str)+"*"+df.單價.astype(str) df.head()

      1

      2

      3

      然后分組聚合:

      def join_func(s): return "/".join(s.dropna()) result = df.groupby(group_columns, as_index=False).agg({"疾病名稱": join_func, "藥品": join_func, "金額匯總": "sum"}) result

      1

      2

      3

      4

      5

      數據處理思路2

      區別在于,前面的代碼的思路是,先填充指定列,聚合時去空值再拼接。這里的思路是一次性全部填充,聚合時去除重復值再拼接。

      完整代碼:

      import pandas as pd def join_func(s): return s.drop_duplicates().str.cat(sep='/') df = pd.read_excel('基礎表/靖宇村.xlsx', sheet_name="基礎表") df.ffill(inplace=True) df = df.astype({"序號": "int16", "年齡": "int16"}, copy=False) df.eval("金額匯總=數量*單價", inplace=True) df.藥品 = df.藥品+df.數量.astype(str)+"*"+df.單價.astype(str) group_columns = ["序號", "姓名", "年齡", "身份證號碼", "家庭住址"] result = df.groupby(group_columns, as_index=False) \ .agg({"疾病名稱": join_func, "藥品": join_func, "金額匯總": "sum"}) result

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      數據處理思路3

      思路:只填充第一列,其余分組列只取第一項。

      import pandas as pd def join_func(s): return s.str.cat(sep='/') df = pd.read_excel('基礎表/靖宇村.xlsx', sheet_name="基礎表") df.序號.ffill(inplace=True) df.年齡.ffill(inplace=True) df = df.astype({"序號": "int16", "年齡": "int16"}, copy=False) df.eval("金額匯總=數量*單價", inplace=True) df.藥品 = df.藥品+df.數量.astype(str)+"*"+df.單價.astype(str) result = df.groupby("序號", as_index=False) \ .agg({"姓名": "first", "年齡": "first", "身份證號碼": "first", "家庭住址": "first", "疾病名稱": join_func, "藥品": join_func, "金額匯總": "sum"}) result

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      將結果寫入模板文件

      下面我們將結果寫入到下面的模板文件中:

      寫出代碼:

      from openpyxl import load_workbook book = load_workbook("合計模板.xlsx") sheet = book["合計表"] length = result.shape[0] data = result.values for i, row in enumerate(sheet[f"A4:H{length+3}"]): for j, cell in enumerate(row): cell.value = data[i, j] book.save("結果表/靖宇村.xlsx")

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      結果:

      整體處理代碼

      已經全部測試完成,下面整理一下完整代碼:

      import os from pathlib import Path import pandas as pd from openpyxl import load_workbook import copy if not os.path.exists("結果表"): os.mkdir("結果表") def join_func(s): return "/".join(s.dropna()) group_columns = ["序號", "姓名", "年齡", "身份證號碼", "家庭住址"] for name in Path("基礎表").glob("[!~]*.xls*"): book = load_workbook("合計模板.xlsx") sheet = book["合計表"] filename = str(name.absolute()) df = pd.read_excel(filename, sheet_name="基礎表") df.ffill(inplace=True) df = df.astype({"序號": "int16", "年齡": "int16"}, copy=False) df.eval("金額匯總=數量*單價", inplace=True) df.藥品 = df.藥品+df.數量.astype(str)+"*"+df.單價.astype(str) group_columns = ["序號", "姓名", "年齡", "身份證號碼", "家庭住址"] result = df.groupby(group_columns, as_index=False) \ .agg({"疾病名稱": join_func, "藥品": join_func, "金額匯總": "sum"}) length = result.shape[0] data = result.values for i, row in enumerate(sheet[f"A4:H{length+3}"]): for j, cell in enumerate(row): cell.value = data[i, j] book.save(f"結果表/{name.name}")

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      執行后,已經順利得到每個村對應的匯總結果。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:華為云ModelArts體驗系列-1:我對ModelArts的認識
      下一篇:04Spark 運行架構
      相關文章
      久久久久亚洲av无码专区蜜芽| 亚洲国产成人九九综合| 亚洲欧洲国产综合| 国产亚洲成av片在线观看 | 亚洲JIZZJIZZ妇女| 亚洲sss综合天堂久久久| 亚洲毛片基地日韩毛片基地| 亚洲色图.com| 久久综合亚洲色一区二区三区| 亚洲av之男人的天堂网站| 亚洲电影一区二区三区| 亚洲日韩精品一区二区三区| 亚洲无线码一区二区三区| 亚洲午夜久久久久久噜噜噜| 亚洲无线码一区二区三区| 亚洲国产精品无码中文字| 亚洲AV日韩精品久久久久久久| 久久久久久a亚洲欧洲AV| 亚洲高清在线视频| 在线观看亚洲一区二区| 亚洲第一成年人网站| 久久精品国产亚洲AV久 | 浮力影院亚洲国产第一页| 亚洲色中文字幕无码AV| 久久亚洲精品成人| 亚洲精品午夜在线观看| 国产精品高清视亚洲精品| 亚洲精品无码成人| 午夜亚洲乱码伦小说区69堂| 国产成人99久久亚洲综合精品 | 亚洲区小说区图片区| 亚洲无人区一区二区三区| 亚洲va在线va天堂va四虎| 亚洲神级电影国语版| 33333在线亚洲| 亚洲av乱码一区二区三区按摩 | 亚洲精品123区在线观看| 亚洲欧美成人av在线观看| 欧洲亚洲国产精华液| 亚洲人成色7777在线观看不卡| 亚洲线精品一区二区三区|