iT邦幫忙

2026 iThome 鐵人賽

DAY 5
0
Software Development

用 Python 打造最順手的良率統計工具:半導體工程師的模組化開發之道系列 第 5

Day 5: 資料處理的最後一哩路 - Pandas 的 csv/ xlsx 輸出設定

  • 分享至 

  • xImage
  •  

本篇目的:了解如何將表格資料輸出成 csv,以及將不同資料輸出到同一個 xlsx 檔案內

前言

“存檔“絕對是資料處理的一個重要環節。實際上我們在確認檢測資料時,大多是輸出成csv/ xlsx這兩種格式,兩個檔案格式的比較如下:

格式 csv xlsx
檔案大小 (同資料量) 較小 較大
寫入速度 較快 較慢
最大可儲存資料數 無限,看硬碟空間 約100萬行
格式保存 就是逗號分隔檔,無法儲存格式 可以儲存文字顏色、儲存格顏色等
適用情境 中途資料,後續還會使用其他東西分析 最終結果,下一步就是投影片等最終呈現的情境

以我們(半導體工程師)的使用情境來說兩種資料格式都會使用到,有可能是輸出 csv 後上拋 MES 系統或是用其他軟體作業;又或是輸出 xlsx 檔後為週會報告做準備。在這裡我會介紹2種儲存 data 的方式,也會介紹將流程封裝成函式 (function) 的方法,為後續建構可維護、可重複使用之模組做準備。

輸出成 csv 檔

Pandas 輸出 csv 檔的方式非常簡單,只要使用 to_csv 並傳入需存檔路徑即可。

要注意的是傳入的路徑需要包含檔名,例如 a.csv 。另外若需要存成特殊的副檔名(但本質上還是 csv),只要將副檔名改成其他字樣即可。

pathlib 是一個管理路徑的模組,而 Path 就是裡面管理路徑的類別 (class)。特別使用 Path 管理路徑的的原因是因為它有許多關於路徑的好用功能,例如抓出檔名等。

from pathlib import Path

# 設定存檔路徑
# "save_path"為Path物件,就是想存檔的路徑
# df_a_data 是一張 dataframe

# Path 物件後加上 "/字串",可以將這串文字加入到路徑中
save_csv_path = save_path/'a.csv' # 注意存檔路徑須包含檔名
df_a_data.to_csv(a_save_csv)

save_cat_path = save_path/'a.cat'  # 副檔名被改成"cat"了
df_a_data.to_csv(save_cat_path) # 將"'a.cat'"存在指定路徑

輸出成 xlsx 檔

若單純地將一張 dataframe 或 series存成 xlsx 檔也非常簡單。跟輸出 csv 類似,只要使用 to_excel 即可。

save_xlsx_path = save_path/'a.xlsx' # 注意存檔路徑須包含檔名
df_a_data.to_excel(a_save_xlsx)

輸出多表格資料到同一 xlsx 檔內

若我們要輸出成 xlsx 檔時通常都是要做報告了,此時一定會需要將資料整理成不同格式,再將表格整理到報告中。因此若能在程式中就將不同表格分門別類到同一檔案內,可以省下很多剪貼時間來更專注在資料呈現上。

輸出多表格到不同張 sheet

若要指定 dataframe 儲存到特定 sheet,在 to_excel 中傳入 sheet_name=sheet名稱 即可。

但因為我們要將多張 dataframe 存入單一 xlsx 中的不同 sheet 中,因此需要建立一個 pd.ExcelWriter 物件,並將它稱為 writerwriter 是讀寫器,可以管理dataframe寫入的行為。

此處使用 with ,再將需要儲存的 dataframe 以 for loop 方式指定給讀寫器 writer 。使用 with 的好處是跑完迴圈後會自動將讀寫器關閉、並且儲存檔案,避免程式執行完畢後讀寫器仍作用,造成後續開啟檔案的異常。

# 注意存檔路徑須包含檔名
all_df_in_axlsx = save_path/'all_in_one_xlsx.xlsx' 

# 先將這些 dataframe 整理到 list 內
all_df_list = [df_a_data, df_b_data, df_c_data]

# 使用"sheet_name="即可指定要貼上的 sheet 名稱
with pd.ExcelWriter(all_df_in_axlsx) as writer:
  
    for i, df in enumerate(all_df_list, start= 1):
      
        # 指定用writer寫入df
        df.to_excel(writer, sheet_name= f'sheet {i}') 

輸出多表格到同一張 sheet

通常同一張 sheet 有多表格時,表格之間一定會有空白列,我們可以使用 startrow=指定列數 來指定要從哪一列開始貼上。另外我們可以在 for loop 中加上平移值,讓每個表格之間有間隔幾列。

all_df_in_asheet = save_path/'all_in_one_sheet.xlsx'

with pd.ExcelWriter(all_df_in_asheet, engine='xlsxwriter') as writer:
    
    row_count = 0 # 列數計數器

    for df in all_df_list:
        
        len_df = df.shape[0] # 取得該df之列數
        df.to_excel(writer, sheet_name="Sheet1", startrow=row_count)
        row_count = row_count + len_df + 3 # 下一個df會從這一個df的下面'3'列開始貼

封裝成可重複使用之函式 (function)

存檔是一定會執行的行為,所以若每次開新專案就要輸入一次上述的指令的話非常浪費時間。因此我們可以將常用指令改寫成函式 (function),而函式的主要結構是 def 名稱(引數) 與內部的運算邏輯。函數的使用方式是設定好後直接在檔案內呼叫、並傳入引數即可,可以想像成將材料(引數)丟入機器中,機器依照設定對材料做處理,最後輸出成品(回傳值)。

https://ithelp.ithome.com.tw/upload/images/20260918/20182319QJMl8VuUiF.png

若以上面的存檔行為舉例,我希望 function 能夠同時支援多表格輸出到不同張 sheet、以及輸出同一張 sheet 並有空格,因此我設計 function 的流程如下:

  1. 設計資料格式可以同時存放"輸出的 sheet 名稱”以及”需輸出的 dataframe”,而且”需輸出的 dataframe”可能是單個也可能是多個

  2. 多個dataframe的話需放入一個 sequence 成為一個單一物件。我這裡選用 list,因為編輯較方便

  3. 因此傳入 function 的 arguments (引數,後面簡稱 Args)會選用 dict,並且將”sheet 名稱”作為 dict 的 key,而”輸出的 dataframe”作為 dict 的 value。另外若需要單 sheet 有多表格,我會以list的方式傳入

    # 定義要輸出的資料結構
    # key 為 Sheet 名稱,value 可以是單一 DataFrame 或一個 DataFrame 清單 (List)
    all_df_dict = {
        'Summary': df_summary,               # 單一表格
        'Wafer_Details': [df_w1, df_w2]      # 多個表格放在同一張 Sheet
    
  4. dict 內的東西都需要處理,因此使用 for loop 遍歷裡面所有項目。
    此外我們有兩個可能的存檔形式(dataframe: 單表寫入單張/ list[dataframe]: 多表寫入單張 ),因此我們需要使用 isinstance 方法來判別 dict 的 value 形式達成分流效果

    with pd.ExcelWriter(save_axlsx, engine='xlsxwriter') as writer:
    
        # 遍歷所有引數內的項目,並分出 key 與 value
        for s_name, content in all_df_dict.items(): 
    
            # 模式 A:若內容是 List,代表要將多個表格存在同一張 Sheet 內
            if isinstance(content, list):
                row_count = 0  # 初始化列數計數器
                for df in content:
                    # 取得該 df 之列數,並指定從 startrow 開始貼上
                    df.to_excel(writer, sheet_name=s_name, startrow=row_count)
    
                    # 計算下一個表格的起始位置:當前列數 + 表格長度 + 間距
                    len_df = df.shape[0]
                    row_count = row_count + len_df + row_spacing + 1 # 加上標題列與間距
    
            # 模式 B:若內容是單一 DataFrame,則直接存入指定 Sheet
            elif isinstance(content, pd.DataFrame):
                content.to_excel(writer, sheet_name=s_name)
    
  5. 將以上項目組合在一起,就是一個完整的 function,這個 function 可以在各種需要存檔的場合重複使用。實際 function 的結構如下:

    def to_excel_flexible(data_dict:dict[str,list[pd.DataFrame] | pd.DataFrame], save_path:Path,*, space_row:int = 3):
        """
        將須輸出資料以{sheet名稱:資料}傳入後,可以輸出成一張xlsx檔
    
        Args:
            data_dict:{sheet名稱:資料},資料會存在指定名稱之sheet內。\n
            若資料以list[pd.DataFrame] 形式傳入,會把這些df存在同一張sheet內
            save_path: 存檔路徑
            space_row: 同一張sheet內,df之間的列間距
    
        """
        with pd.ExcelWriter(save_path,engine='xlsxwriter') as writer:
    
            for s_name, content in data_dict.items():
    
                print(s_name)
    
                if isinstance(content,list):
                    row_count = 0 # 初始化列數計數器
    
                    for df in content:
    
                        df.to_excel(writer, sheet_name=s_name, startrow=row_count)
    
                        # 計算下一個表格的起始位置:當前列數 + 表格長度 + 間距
                        len_df = df.shape[0]
                        # 加上標題列與間距
                        row_count = row_count + len_df + row_spacing + 1 
    
                elif isinstance(content, pd.DataFrame):
                    content.to_excel(writer, sheet_name= s_name)
    

建構 function 時的思考方向

我們在工作中一定碰過大大小小的專案。專案規劃前會先確認專案目的與期限、然後盤點可用資源,然後才是列出執行細節。專案執行中也有可能因為需求或可用資源改變,導致要回頭修改執行方式。我們執行專案並且動態調整執行方式,最後達到專案成果。並且若該專案會重複執行,會將執行方式寫成 SOP 方便未來執行。

建構 function (又或是整個程式設計) 的思考模式其實跟專案非常相近,先確認這個 function 的目的、確認會傳入的資料以及適合的資料結構、然後設計執行流程,流程設計時又可能回去改資料結構。最後當流程確定時,才建構 function,讓未來有需求時可以實際調用。

Function 建構的方式如下圖:

https://ithelp.ithome.com.tw/upload/images/20260918/201823195QaBE58HJS.png

To be continued →

除了表格外,mapping 圖也是很常用的呈現形式


上一篇
Day 4:週會救星 - 應用 Groupby 與 Pivot table 的組合快速做出各式報表
系列文
用 Python 打造最順手的良率統計工具:半導體工程師的模組化開發之道5
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言