# Pandas模組與資料型態 / Series / DataFrames 學習筆記 <!-- 前言:學習的是方法,之後再去查對應的語法 --> > [TOC] 課堂老師提供的學習方式: 閱讀官方API文件,以及查看資料型態以及方法 舉例: ``` print(type(df.loc[0,'bdy'])) print(dir(df.loc[0,'bdy'])) ``` :::success 台灣行列用語與大陸用法不同 查看網路資料須留意 直行橫列 (前列,後行) ::: --- 隨筆記錄區: pandas 最強函式: apply numpy 的小孩:pandas > 延伸筆記:[NUMPY Matplotlib 學習筆記](/YGK1t_tZSoOa8xHoTS2zGA) 獲得資料後讀取,產生一維或二維資料 資料格式: 1. CSV, Excel 可使用 Pandas 模組讀取 2. Text 文字檔案,使用 BIF 內建函式讀取 Pandas 專屬資料型態認識 學習如何新增/修改/刪除/排序/索引/切片 額外學習如何處理日期資料, what is 列索引物件 行索印物件 最後將整理好的資料視覺化 可以使用的工具: * PowerBI * matplotlib * seaborn * plotly * streamlit * tkinter 步驟:讀取檔案,轉成 pandas 可讀取形式,修改欄位名稱,查看資料型態 產生 DataFrames 的方式 字典 key 當行索引 或是多組列資料,指定行列索引 ![Xnip2024-08-23_10-41-39](https://hackmd.io/_uploads/rJ5DiOrjC.png) --- # Pandas Series 一維資料物件 第一種查看方式: 使用字典建立 Series 使用字典建立 Series 時,字典的鍵成為索引,值成為數據。 官方提供的案例: ```python import pandas as pd d = {'a': 1, 'b': 2, 'c': 3} ser = pd.Series(data=d, index=['a', 'b', 'c']) print(ser) ``` output : ``` a 1 b 2 c 3 dtype: int64 ``` 第二種查看方式: 將資料轉成 dataframe 後 `df.dtypes` 會回傳一個 Series 裡面儲存每個欄位的資料型態 ![Xnip2024-08-23_10-59-48](https://hackmd.io/_uploads/BJrVidSjC.png) ```python= import pandas as pd f = open("myscore.txt") list_all = f.readlines() # print(list_all) score = [] # 資料預處理成 pandas 可讀取形式 for item in list_all: a = item.split('\t') score.append(a) # print(a) # print(score) df = pd.DataFrame(score) df.columns = ["學號","姓名","國文","英文","數學","血型","生日"] print(type(df.dtypes)) print(df.dtypes) print(df) f.close() ``` # Series / dataframe 合併資料 參考資料: https://medium.com/@hui509/pandas-新增-series-或-dataframe-bb41c4098603 https://pandas.pydata.org/docs/reference/api/pandas.concat.html#pandas.concat 要注意 series 是 一維 ```python= New = pd.Series(['USA','Canada','UK']) # Solution1 - _append # New_countries = city._append(New,ignore_index=True) # 魔法函式 進階使用 先不用學 # Solution2 - concat New_countries = pd.concat([city,New],ignore_index=True) # ignore_index 重新索引避免重複,確保索引的連續性和唯一性 # 一維其實可以直接用串列形式,可以直接相加合併,無需使用 pd 模組也可 print(city) print(New_countries) ``` # 修改資料型態 astype https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.astype.html#pandas.DataFrame.astype ```python= df.columns = ["學號","姓名","國文","英文","數學","血型","生日"] df = df.astype({"國文":"uint8"}) ``` 用 `df.info()` 查看表格結構 ``` <class 'pandas.core.frame.DataFrame'> RangeIndex: 29 entries, 0 to 28 Data columns (total 7 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 學號 29 non-null object 1 姓名 29 non-null object 2 國文 29 non-null uint8 3 英文 29 non-null object 4 數學 29 non-null object 5 血型 29 non-null object 6 生日 29 non-null object dtypes: object(6), uint8(1) memory usage: 1.5+ KB None ``` 備註:他會回傳一個新的,要重新賦予 ![image](https://hackmd.io/_uploads/SyGFmYHiA.png) # 新增欄位/索引資料 > df["欄位"] = list(range(1,10)) > df.loc["索引"] = list(range(1,10)) ``` # numpy 自動廣播的概念 # numpy arrange df['平均'] = 0 # df['平均'] = list(range(1,30)) ``` 其中要特別注意的是 Dataframe: 新增 col 直行: df.loc[:,'直行'] 可以縮寫成 df['直行'] 新增 row 橫行: df.loc[1000] 不可以縮寫 ```python= data = {'name':['Larry','Lin'], 'bdy':['1130','1212']} df2 = pd.DataFrame(data, index=['1', '2']) # print(df2) df2.loc[3, :] = ['Wang', '0101'] print(df2) # 新增 col 'blood' df2['blood'] = 1000 # df2[:,'blood'] 是錯誤的,真正的用法為 df2.loc[:,'blood'] print(df2) # _append 不好用不要用,還要考慮 index ``` # concat 新增多筆資料 ``` data = {'name':['Larry','Lin'], 'bdy':['1130','1212']} df2 = pd.DataFrame(data) # print(df2) # 單筆資料 df2.loc[2] = ['Wang','0101'] print(df2) # df2['blood'] = 1000 # df2[:,'blood'] = 1000 # print(df2) # _append 不好用不要用,還要考慮 index # 多筆資料 data2 = {'blood':['A','B','AB']} df3 = pd.DataFrame(data2) new = pd.concat([df2,df3], axis=1) print(new) # axis=0 為直向合併 ``` # 刪除資料 x 沒記錄到 # 修改資料 用文字或是位置當作索引,選取位置 > .loc["行的索引值"] ```python= # 修改資料,索引與切片 # df['平均'] = 0 # df['平均'] = list(range(1,30)) df.loc[0,'平均'] = round(( df.loc[0,'ch'] + df.loc[0,'en'] + df.loc[0,'math'] ) / 3,2) # 用標籤選取資料 # 單行 column df_avg = df.loc[:,'avg'] # 可簡寫成 df_avg = df['avg'] ``` 老師說明要區分是處理 series 還是 dataframe 網路上都在教 dataframe 的例子 下列是使用 Series 的 round 函式 (dataframe一樣有) ```python= # 計算平均分並新增為新的一欄「平均」 df['avg'] = ( (df['ch'] + df['en'] + df['math']) / 3 ).round(2) ``` # 排序 https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.sort_values.html#pandas.DataFrame.sort_values series rank 用在排名,ascending=False ``` df['rank'] = df['avg'].rank(method='min',ascending=False).astype(int) df = df.sort_values(['rank']) ``` ``` import pandas as pd # 創建一個含有重複值的 Series data = pd.Series([70, 90, 70, 80, 90, 70]) # 使用不同的 method 進行排名 rank_average = data.rank(method='average', ascending=False) # 平均排名 rank_min = data.rank(method='min', ascending=False) # 最低排名 rank_max = data.rank(method='max', ascending=False) # 最高排名 # 輸出結果 print("Original Data:\n", data) print("Rank by Average:\n", rank_average) print("Rank by Min:\n", rank_min) print("Rank by Max:\n", rank_max) ``` dataframe rank https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.rank.html#pandas.DataFrame.rank # series strip https://pandas.pydata.org/docs/reference/api/pandas.Series.str.strip.html#pandas.Series.str.strip # 日期處理 時間轉字串 str from time https://pandas.pydata.org/docs/reference/api/pandas.DatetimeIndex.strftime.html#pandas.DatetimeIndex.strftime Function is not implemented. Use pd.to_datetime(). str phase time https://pandas.pydata.org/docs/reference/api/pandas.Timestamp.strptime.html#pandas.Timestamp.strptime ![image](https://hackmd.io/_uploads/Byn3CsBiA.png) 民國年要改成西元年 使用 apply 函式,去寫自定義 func ```python= # Pandas BIF # df['bdy'] = pd.to_datetime() # 正常用法:轉換日期,並調整年份格式 # df['bdy'] = pd.to_datetime(df['bdy'], errors='coerce', format='%y-%m-%d') # 民國轉西元 用迴圈方式 # for index, value in enumerate(df['bdy']): # year, month, day = value.split("-") # 分割字符串得到年、月、日 # year = int(year) + 1911 # 將民國年轉換為公元年 # new_date = f"{year}-{month}-{day}" # 格式化新的日期字符串 # df.loc[index, 'bdy'] = new_date # 使用 index 更新 df # # df['bdy'] = pd.to_datetime(df['bdy']) def right_date(value): year, month, day = value.split("-") year = int(year) + 1911 return f"{year}-{month}-{day}" # 將民國年轉換為西元年 df['bdy'] = df['bdy'].apply(right_date) # 然後將這些字符串轉換為 datetime df['bdy'] = pd.to_datetime(df['bdy']) ``` pandas 有 timestamp 物件 https://timestamp.onlinealat.com https://pandas.pydata.org/docs/reference/api/pandas.Timestamp.year.html pandas series 有 year / month / day https://pandas.pydata.org/docs/reference/api/pandas.Series.dt.year.html# ## pandas.to_datetime https://pandas.pydata.org/docs/reference/api/pandas.to_datetime.html#pandas-to-datetime # DataFrame 二維資料物件 直行 columns 橫列 index 與前面一維 Series 互相比較 (未騰入筆記) # 學習資源: (大部分都是)用 dataframe 舉例的教學: https://ithelp.ithome.com.tw/articles/10343746 用實際案例舉例如何操作,製圖讚讚,一系列資料科學相關文章 https://medium.com/ntu-data-analytics-club/python-advanced-一起來用-pandas-玩轉數據-6d06d805941a Day10Learning Pandas - Series、DataFrame、Index https://ithelp.ithome.com.tw/articles/10204656 智能股市分析師:Python股價歷史資料自動化爬蟲與分析 https://hackmd.io/@Tj7zBL4CS-CymiaJeR8Uew/SkZ8TFvB6