python資料框新建一個列並賦值_tidyfst vs pandas(4):資料框的使用
阿新 • • 發佈:2021-01-07
技術標籤:python資料框新建一個列並賦值
作者:黃天元,復旦大學博士在讀,熱愛資料科學與開源工具(R),致力於利用資料科學迅速積累行業經驗優勢和科學知識發現,涉獵內容包括但不限於資訊計量、機器學習、資料視覺化、應用統計建模、知識圖譜等,著有《R語言高效資料處理指南》(《R語言資料高效處理指南》(黃天元)【摘要 書評 試讀】- 京東圖書)。知乎專欄:R語言資料探勘。郵箱:[email protected]歡迎合作交流。
資料框在R中是原生的資料結構,而Python中則沒有,也就是沒有Pandas就沒有dataframe的一種狀況。下面我們來用Jupyter Notebook Viewer中提供的程式碼來檢視pandas中資料框的特性,程式碼如下:
>>> import pandas as pd >>> import numpy as np >>> >>> # (a)建立一個DataFrame >>> df = pd.DataFrame({'col1':list('abcde'),'col2':range(5,10),'col3':[1.3,2.5,3.6,4.6,5.8]}, ... index=list('一二三四五')) >>> df col1 col2 col3 一 a 5 1.3 二 b 6 2.5 三 c 7 3.6 四 d 8 4.6 五 e 9 5.8 >>> >>> # (b)從DataFrame取出一列為Series >>> df['col1'] 一 a 二 b 三 c 四 d 五 e Name: col1, dtype: object >>> type(df) <class 'pandas.core.frame.DataFrame'> >>> type(df['col1']) <class 'pandas.core.series.Series'> >>> >>> # (c)修改行或列名 >>> df.rename(index={'一':'one'},columns={'col1':'new_col1'}) new_col1 col2 col3 one a 5 1.3 二 b 6 2.5 三 c 7 3.6 四 d 8 4.6 五 e 9 5.8 >>> >>> # (d)呼叫屬性和方法 >>> df.index Index(['一', '二', '三', '四', '五'], dtype='object') >>> df.columns Index(['col1', 'col2', 'col3'], dtype='object') >>> df.values array([['a', 5, 1.3], ['b', 6, 2.5], ['c', 7, 3.6], ['d', 8, 4.6], ['e', 9, 5.8]], dtype=object) >>> df.shape (5, 3) >>> df.mean() col2 7.00 col3 3.56 dtype: float64 >>> >>> # (e)索引對齊特性 >>> # 這是Pandas中非常強大的特性,不理解這一特性有時就會造成一些麻煩 >>> df1 = pd.DataFrame({'A':[1,2,3]},index=[1,2,3]) >>> df2 = pd.DataFrame({'A':[1,2,3]},index=[3,1,2]) >>> df1-df2 A 1 -1 2 -1 3 2 >>> >>> # (f)列的刪除與新增 >>> # 對於刪除而言,可以使用drop函式或del或pop >>> df.drop(index='五',columns='col1') #設定inplace=True後會直接在原DataFrame中改動 col2 col3 一 5 1.3 二 6 2.5 三 7 3.6 四 8 4.6 >>> >>> df['col1']=[1,2,3,4,5] >>> del df['col1'] >>> df col2 col3 一 5 1.3 二 6 2.5 三 7 3.6 四 8 4.6 五 9 5.8 >>> >>> # pop方法直接在原來的DataFrame上操作,且返回被刪除的列,與python中的pop函式類似 >>> df['col1']=[1,2,3,4,5] >>> df.pop('col1') 一 1 二 2 三 3 四 4 五 5 Name: col1, dtype: int64 >>> df col2 col3 一 5 1.3 二 6 2.5 三 7 3.6 四 8 4.6 五 9 5.8 >>> >>> # 可以直接增加新的列,也可以使用assign方法 >>> df1['B']=list('abc') >>> df1 A B 1 1 a 2 2 b 3 3 c >>> >>> df1.assign(C=pd.Series(list('def'))) A B C 1 1 a e 2 2 b f 3 3 c NaN >>> #思考:為什麼會出現NaN?(提示:索引對齊)assign左右兩邊的索引不一樣,請問結果的索引誰說了算? >>> >>> # 但assign方法不會對原DataFrame做修改 >>> df1 A B 1 1 a 2 2 b 3 3 c >>> >>> # (g)根據型別選擇列 >>> df.select_dtypes(include=['number']).head() col2 col3 一 5 1.3 二 6 2.5 三 7 3.6 四 8 4.6 五 9 5.8 >>> df.select_dtypes(include=['float']).head() col3 一 1.3 二 2.5 三 3.6 四 4.6 五 5.8 >>> >>> # (h)將Series轉換為DataFrame >>> s = df.mean() >>> s.name='to_DataFrame' >>> s col2 7.00 col3 3.56 Name: to_DataFrame, dtype: float64 >>> s.to_frame() to_DataFrame col2 7.00 col3 3.56 >>> >>> # 使用T符號可以轉置 >>> s.to_frame().T col2 col3 to_DataFrame 7.0 3.56
在R中的實現如下:
> library(tidyfst) > library(stringr) > > # (a)建立一個data.frame > df = data.frame(col1=letters[1:5], + col2=5:9, + col3=c(1.3,2.5,3.6,4.6,5.8), + row.names = str_split("一二三四五", + "",simplify = T)) > df col1 col2 col3 一 a 5 1.3 二 b 6 2.5 三 c 7 3.6 四 d 8 4.6 五 e 9 5.8 > > # (b)從DataFrame取出一列 > df['col1'] col1 一 a 二 b 三 c 四 d 五 e > class(df) [1] "data.frame" > class(df['col1']) #取出一列依然是資料框 [1] "data.frame" > # 要取出向量,使用`[[` > df[['col1']] [1] "a" "b" "c" "d" "e" > class(df[['col1']]) [1] "character" > > # (c)修改行或列名 > df2 = copy(df) > rownames(df2)[1] = "one" > colnames(df2)[1] = "new_col1" > df2 new_col1 col2 col3 one a 5 1.3 二 b 6 2.5 三 c 7 3.6 四 d 8 4.6 五 e 9 5.8 > > # (d)呼叫屬性和方法 > rownames(df) [1] "一" "二" "三" "四" "五" > colnames(df) [1] "col1" "col2" "col3" > as.matrix(df) col1 col2 col3 一 "a" "5" "1.3" 二 "b" "6" "2.5" 三 "c" "7" "3.6" 四 "d" "8" "4.6" 五 "e" "9" "5.8" > dim(df) [1] 5 3 > df %>% summarise_vars(is.numeric,mean) col2 col3 <num> <num> 1: 7 3.56 > > # (e)索引對齊特性 > # r沒有這個特性,在data.table體系中甚至沒有行索引,而是應該構造一個索引列,需要對齊可直接使用連線(join) > > # (f)列的刪除與新增 > df2 = copy(df) > df2['col1'] = NULL #賦值NULL可以刪除列 > df2 = df2[-5,] # 減號可以取出任意行 > df2 col2 col3 一 5 1.3 二 6 2.5 三 7 3.6 四 8 4.6 > > # (g)根據型別選擇列 > df %>% select_dt(is.numeric) %>% head col2 col3 <int> <num> 1: 5 1.3 2: 6 2.5 3: 7 3.6 4: 8 4.6 5: 9 5.8 > df %>% select_dt(is.double) %>% head col3 <num> 1: 1.3 2: 2.5 3: 3.6 4: 4.6 5: 5.8 > > # (h)將Series轉換為DataFrame > ## r中自動轉換 > s = df %>% summarise_vars(is.numeric,mean) > ## 轉置 > t_dt(s) V1 col2 7.00 col3 3.56
稍微談談感想:
1、Python中獲得一個從5到9的所有正整數,是用range(5,10),這是跟下標從0開始一樣的反人類設定,讓人抓狂。R中是5:9,比較人性化。
2、Python在完成這些資料科學任務中,總是充滿計算機思想,比如pop的使用。因此它對計算機背景的使用者友好,但是對於非計算機背景的同學可能就是各種問號。但我相信這跟語言本身不一定有關,而是與介紹者和工具設計者的引導有關。
3、Pandas中索引對齊的屬性,可能是個坑,會給部分資料分析埋雷。R中原生資料框還保留行名稱(索引)這個屬性,但是data.table和tibble格式都已經不支援行名稱了,而是推薦大家自定義一個索引列。少做設定,多讓使用者自己選擇,是個好思路。