1. 程式人生 > 其它 >python資料框新建一個列並賦值_tidyfst vs pandas(4):資料框的使用

python資料框新建一個列並賦值_tidyfst vs pandas(4):資料框的使用

技術標籤: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格式都已經不支援行名稱了,而是推薦大家自定義一個索引列。少做設定,多讓使用者自己選擇,是個好思路。