基礎資料框操作技巧

Tidy datasets are all alike, but every messy dataset is messy in its own way.

Hadley Wickham

掌控資料的能力被總稱為 Data Wrangling(或者 Data Munging),這樣的能力建構在對資料結構的理解與資料框的操作技巧;在面對未來的課題,不論是探索性資料分析(Exploratory Data Analysis,EDA)、統計分析、機器學習或者溝通呈現之前,有極大比例的時間花費在清理並重組資料,在如何掌控資料:認識常見的資料結構之中我們簡介了資料科學團隊常面對的資料結構,其中佔有主流地位的是表格式資料(Tabular Data),在 Python 與 R 語言中,都是以資料框(Data Frame)來處理表格式資料。

拜 Excel 試算表廣受歡迎之賜,資料框對我們並不如陣列或者清單那般陌生,這樣的二維資料結構,每列代表一個觀測值,每欄代表一個變數,就像是增強了列索引值與欄索引值的矩陣,並容許每一個欄位(變數)具有自己的型別。

建立

建立資料框的方式有兩個,一為手動輸入資料,二為載入表格式資料(CSV、TXT 或者試算表)。我們可以分別在 Python 與 R 語言中利用 pandas.DataFrame()data.frame() 函數手動輸入資料框的資料。

以下展示的順序先是 Python 然後是 R 語言。

手動輸入一個 1995 至 1996 年球季芝加哥公牛隊先發陣容的資料框,這是一個 5 x 2 的資料框,紀錄五個先發球員的背號與姓名。

import pandas as pd

numbers = [9, 23, 33, 91, 13]
players = ["Ron Harper", "Michael Jordan", "Scottie Pippen", "Dennis Rodman", "Luc Longley"]
df = pd.DataFrame()
df["number"] = numbers
df["player"] = players
df
1
2
3
4
5
6
7
8

5 x 2 的資料框,紀錄五個先發球員的背號與姓名

值得注意的是,在 R 語言中資料框預設儲存文字的型別是一種稱為 factor 的型別,這個型別比單純的文字陣列有較多功能但同時也有較多眉角得注意,通常不推薦對於 R 語言不夠熟悉的使用者去處理 factor 型別,因此我們在 data.frame() 函數加入了一個參數 stringsAsFactors = FALSE

numbers <- c(9, 23, 33, 91, 13)
players <- c("Ron Harper", "Michael Jordan", "Scottie Pippen", "Dennis Rodman", "Luc Longley")
df <- data.frame(number = numbers, player = players, stringsAsFactors = FALSE)
View(df)
1
2
3
4

5 x 2 的資料框,紀錄五個先發球員的背號與姓名

第二個方式是載入一個表格式檔案例如:gapminder.csv 成為資料框,這是一個 1704 x 6的資料框,紀錄 142 個國家 1952 至 2007 年每五年的資訊快照(snapshot)。我們可以分別在 Python 與 R 語言中利用 pandas.read_csv()read.csv() 函數載入資料,而 read.csv() 函數同樣也能加入參數 stringsAsFactors = FALSE 以避免讓使用者去處理 factor 型別。

import pandas as pd

csv_url = "https://storage.googleapis.com/learn_pd_like_tidyverse/gapminder.csv"
df = pd.read_csv(csv_url)
df
1
2
3
4
5

1704 x 6的資料框,紀錄 142 個國家 1952 至 2007 年每五年的資訊快照

csv_url <- "https://storage.googleapis.com/learn_pd_like_tidyverse/gapminder.csv"
df <- read.csv(csv_url, stringsAsFactors = FALSE)
View(df)
1
2
3

1704 x 6的資料框,紀錄 142 個國家 1952 至 2007 年每五年的資訊快照

檢視

Python

在 Python pandas 中可以透過下列幾個資料框方法或屬性檢視:

  • df.head():查看前五列觀測值,可以加入參數 n 觀看前 n 列觀測值
  • df.tail():查看末五列觀測值,可以加入參數 n 觀看末 n 列觀測值
  • df.info():查看資料框的複合資訊,包含型別、外觀與變數型別等
  • df.describe():查看數值變數的描述性統計,包含最小值、最大值、平均數與中位數等
  • df.shape:查看資料框的外觀,以 tuple 的型別回傳,(m, n) 表示 m 列觀測值,n 欄變數
  • df.columns:查看資料框的變數名稱
  • df.index:查看資料框的列索引值
import pandas as pd

csv_url = "https://storage.googleapis.com/learn_pd_like_tidyverse/gapminder.csv"
df = pd.read_csv(csv_url)
df.head()     # 查看前五列觀測值
df.tail()     # 查看末五列觀測值
df.info()     # 查看資料框的複合資訊
df.describe() # 查看數值變數的描述性統計
df.shape      # 查看資料框的外觀
1
2
3
4
5
6
7
8
9

df.head() 查看前五列觀測值

df.tail() 查看末五列觀測值

df.info() 查看資料框的複合資訊:

## <class 'pandas.core.frame.DataFrame'>
## RangeIndex: 1704 entries, 0 to 1703
## Data columns (total 6 columns):
## country      1704 non-null object
## continent    1704 non-null object
## year         1704 non-null int64
## lifeExp      1704 non-null float64
## pop          1704 non-null int64
## gdpPercap    1704 non-null float64
## dtypes: float64(2), int64(2), object(2)
## memory usage: 80.0+ KB
1
2
3
4
5
6
7
8
9
10
11

df.describe() 查看數值變數的描述性統計

df.shape 查看資料框的外觀:

## (1704, 6)
1

df.columns 查看資料框的變數名稱:

## Index(['country', 'continent', 'year', 'lifeExp', 'pop', 'gdpPercap'], dtype='object')
1

df.index 查看資料框的列索引值:

## RangeIndex(start=0, stop=1704, step=1)
1

R 語言

在 R 語言中可以透過下列幾個函數檢視資料框:

  • head():查看前六列觀測值,可以加入參數 n 觀看前 n 列觀測值
  • tail():查看末六列觀測值,可以加入參數 n 觀看末 n 列觀測值
  • str():structure 的簡寫,可以查看資料框的複合資訊,包含型別、外觀與變數型別等
  • summary():查看描述性統計,包含最小值、最大值、平均數與中位數等
  • dim():dimension 的簡寫,可以查看資料框的外觀,以 vector 的型別回傳,[1] m n 表示 m 列觀測值,n 欄變數
  • nrow():查看資料框有幾個列
  • ncol():查看資料框有幾個欄
  • colnames():查看資料框所有的變數名稱
  • row.names():查看資料框的列索引值,以文字型別回傳
csv_url <- "https://storage.googleapis.com/learn_pd_like_tidyverse/gapminder.csv"
df <- read.csv(csv_url, stringsAsFactors = FALSE)
head(df)           # 查看前六列觀測值
tail(df)           # 查看末六列觀測值
str(df)            # 查看資料框的複合資訊
summary(df)        # 查看描述性統計
dim(df)            # 查看資料框的外觀
nrow(df)           # 查看資料框有幾個列
ncol(df)           # 查看資料框有幾個欄
colnames(df)       # 查看資料框所有的變數名稱
row.names(df)[1:6] # 查看資料框的列索引值
1
2
3
4
5
6
7
8
9
10
11

head() 查看前六列觀測值

tail() 查看前六列觀測值

str() 查看資料框的複合資訊

summary() 查看描述性統計

dim() 查看資料框的外觀:

## [1] 1704    6
1

nrow() 查看資料框有幾個列:

## [1] 1704
1

ncol() 查看資料框有幾個欄:

## [1] 6
1

colnames() 查看資料框所有的變數名稱:

## [1] "country"   "continent" "year"      "lifeExp"   "pop"       "gdpPercap"
1

row.names() 查看資料框的列索引值:

## [1] "1" "2" "3" "4" "5" "6"
1

篩選

常見有兩種作法,一是利用觀測值的所在位置(列索引值,欄索引值)進行篩選,二是利用判斷條件產生布林(邏輯)值的陣列再根據該陣列作為篩選依據,透過篩選也能夠實踐刪除觀測值這個操作技巧。

在 Python pandas 中可以使用 df.loc[m, n]df.iloc[m, n] 兩個方法指定觀測值所在位置,兩者用法差在於 df.loc[] 完全憑藉列索引值與欄索引值的標籤;而 df.iloc[] 完全憑藉相對位置(因此方法中的 i 乃是整數 integer 的示意)。

Python

舉例來說 1995 至 1996 年球季芝加哥公牛隊先發陣容的資料框,記錄五個先發球員的背號與姓名,並且以鋒衛(Guard/Forward)位置作為資料框列索引值。

import pandas as pd

numbers = [9, 23, 33, 91, 13]
players = ["Ron Harper", "Michael Jordan", "Scottie Pippen", "Dennis Rodman", "Luc Longley"]
df = pd.DataFrame()
df["number"] = numbers
df["player"] = players
df.index = ["PG", "SG", "SF", "PF", "C"]
df
1
2
3
4
5
6
7
8
9

以鋒衛(Guard/Forward)位置作為資料框列索引值

在索引值不是預設 RangeIndex(start=0, stop=5, step=1) 的時候比較容易區別 .loc[].iloc[] 之間的差異。我們希望選出 Michael Jordan、Scottie Pippen 與 Dennis Rodman:

import pandas as pd

numbers = [9, 23, 33, 91, 13]
players = ["Ron Harper", "Michael Jordan", "Scottie Pippen", "Dennis Rodman", "Luc Longley"]
df = pd.DataFrame()
df["number"] = numbers
df["player"] = players
df.index = ["PG", "SG", "SF", "PF", "C"]
df.loc[["SG", "SF", "PF"], ["number", "player"]] # 以索引為準
df.iloc[[1, 2, 3], [0, 1]]                       # 以位置為準
1
2
3
4
5
6
7
8
9
10

選出 Michael Jordan、Scottie Pippen 與 Dennis Rodman

如果利用判斷條件選擇,那麼不論透過球衣背號或球員姓名都可以選出。

import pandas as pd

numbers = [9, 23, 33, 91, 13]
players = ["Ron Harper", "Michael Jordan", "Scottie Pippen", "Dennis Rodman", "Luc Longley"]
df = pd.DataFrame()
df["number"] = numbers
df["player"] = players
df.index = ["PG", "SG", "SF", "PF", "C"]
is_trio = df["number"].isin([23, 33, 91]) # 透過球衣背號
print(is_trio)
df[is_trio]
1
2
3
4
5
6
7
8
9
10
11
import pandas as pd

numbers = [9, 23, 33, 91, 13]
players = ["Ron Harper", "Michael Jordan", "Scottie Pippen", "Dennis Rodman", "Luc Longley"]
df = pd.DataFrame()
df["number"] = numbers
df["player"] = players
df.index = ["PG", "SG", "SF", "PF", "C"]
is_trio = df["player"].isin(["Michael Jordan", "Scottie Pippen", "Dennis Rodman"]) # 透過球員姓名
print(is_trio)
df[is_trio]
1
2
3
4
5
6
7
8
9
10
11

透過球衣背號或球員姓名

R 語言

在 R 語言中亦能夠透過 df[m, n] 利用位置篩選觀測值以及利用判斷條件選擇這兩種方法。

numbers <- c(9, 23, 33, 91, 13)
players <- c("Ron Harper", "Michael Jordan", "Scottie Pippen", "Dennis Rodman", "Luc Longley")
df <- data.frame(number = numbers, player = players, stringsAsFactors = FALSE)
df[c(2, 3, 4), ]                                                                 # 透過位置
is_trio <- df$number %in% c(23, 33, 91)                                          # 透過球衣背號
is_trio
df[is_trio, ]
is_trio <- df$player %in% c("Michael Jordan", "Scottie Pippen", "Dennis Rodman") # 透過球員姓名
is_trio
df[is_trio, ]
1
2
3
4
5
6
7
8
9
10

透過位置

透過球衣背號

透過球員姓名

透過判斷條件也可以考慮使用 dplyr 套件的 filter() 函數。

library(dplyr)

numbers <- c(9, 23, 33, 91, 13)
players <- c("Ron Harper", "Michael Jordan", "Scottie Pippen", "Dennis Rodman", "Luc Longley")
df <- data.frame(number = numbers, player = players, stringsAsFactors = FALSE)
df %>% 
  filter(number %in% c(23, 33, 91)) # filter(player %in% c("Michael Jordan", "Scottie Pippen", "Dennis Rodman"))
1
2
3
4
5
6
7

使用 dplyr 套件的 filter() 函數

選擇

依照變數名稱或者所在位置選擇,透過選擇也能夠實踐刪除變數與調整變數在資料框中的位置這兩個操作技巧。

Python

在 Python pandas 中可以透過 df.coldf["col"] 選出資料框的單一個變數,這時會轉換為 pandas.core.series.Series 的型別;透過 df[["col1", "col2"]] 則能夠選出資料框中的多個變數,這時型別依然是資料框。

import pandas as pd

numbers = [9, 23, 33, 91, 13]
players = ["Ron Harper", "Michael Jordan", "Scottie Pippen", "Dennis Rodman", "Luc Longley"]
df = pd.DataFrame()
df["number"] = numbers
df["player"] = players
print(df["player"])
print(type(df["player"]))
df[["player", "number"]]
1
2
3
4
5
6
7
8
9
10

依照變數名稱選擇

若要依照變數位置選擇,得仰賴 .iloc[],全選可以使用 : 來表示。

import pandas as pd

numbers = [9, 23, 33, 91, 13]
players = ["Ron Harper", "Michael Jordan", "Scottie Pippen", "Dennis Rodman", "Luc Longley"]
df = pd.DataFrame()
df["number"] = numbers
df["player"] = players
print(df.iloc[:, 1])
print(type(df.iloc[:, 1]))
df.iloc[:, [1, 0]]
1
2
3
4
5
6
7
8
9
10

依照變數位置選擇

R 語言

在 R 語言中能夠透過 df$coldf[, "col"] 選擇單一個變數,這時會轉換為 vector,透過 df[, c("col1", "col2")] 則能夠選出資料框中的多個變數,這時型別依然是資料框。

numbers <- c(9, 23, 33, 91, 13)
players <- c("Ron Harper", "Michael Jordan", "Scottie Pippen", "Dennis Rodman", "Luc Longley")
df <- data.frame(number = numbers, player = players, stringsAsFactors = FALSE)
df$player
df[, "player"]
df[, c("player", "number")]
1
2
3
4
5
6

依照變數名稱選擇

透過變數名稱選擇也可以考慮使用 dplyr 套件的 select() 函數。

library(dplyr)

numbers <- c(9, 23, 33, 91, 13)
players <- c("Ron Harper", "Michael Jordan", "Scottie Pippen", "Dennis Rodman", "Luc Longley")
df <- data.frame(number = numbers, player = players, stringsAsFactors = FALSE)
df %>% 
  select(player, number)
1
2
3
4
5
6
7

使用 dplyr 套件的 select() 函數

亦可以依照變數位置選擇。

numbers <- c(9, 23, 33, 91, 13)
players <- c("Ron Harper", "Michael Jordan", "Scottie Pippen", "Dennis Rodman", "Luc Longley")
df <- data.frame(number = numbers, player = players, stringsAsFactors = FALSE)
df[, 2]
df[, c(2, 1)]
1
2
3
4
5

依照變數位置選擇

排序

依照某個或多個變數大小排序整個資料框的觀測值是常見的應用,可以遞增排序(由小到大)或者遞減排序(由大到小),假使面對文字型別的變數遞增排序,那麼就是按照字母順序 a-zA-Z(R 語言)或者 A-Za-z(Python)。

Python

在 Python pandas 中我們可以使用 df.sort_index()df.sort_values() 來排序資料框,預設的排序方式均為遞增排序(ascending=True),如果希望調整為遞減排序,指定 ascending=False 即可。

首先試試看 df.sort_index(),利用鋒衛的位置字母順序排序資料框。

import pandas as pd

numbers = [9, 23, 33, 91, 13]
players = ["Ron Harper", "Michael Jordan", "Scottie Pippen", "Dennis Rodman", "Luc Longley"]
df = pd.DataFrame()
df["number"] = numbers
df["player"] = players
df.index = ["PG", "SG", "SF", "PF", "C"]
df.sort_index()                # 依照索引遞增排序
df.sort_index(ascending=False) # 依照索引遞減排序
1
2
3
4
5
6
7
8
9
10

依照索引遞增排序

依照索引遞減排序

接著試試看 df.sort_values(),利用年份排序資料框。

import pandas as pd

csv_url = "https://storage.googleapis.com/learn_pd_like_tidyverse/gapminder.csv"
df = pd.read_csv(csv_url)
df.sort_values(by="year").head()                  # 依照 year 遞增排序
df.sort_values(by="year", ascending=False).head() # 依照 year 遞減排序
1
2
3
4
5
6

依照 year 遞增排序

依照 year 遞減排序

也能夠輸入多個變數排序,像是先依照 year 遞增排序再依照 continent 遞減排序。

import pandas as pd

csv_url = "https://storage.googleapis.com/learn_pd_like_tidyverse/gapminder.csv"
df = pd.read_csv(csv_url)
df.sort_values(by=["year", "continent"], ascending=[True, False]).head() # 依照 year 遞增排序再依照 continent 遞減排序
1
2
3
4
5

先依照 year 遞增排序再依照 continent 遞減排序

R 語言

在 R 語言中我們使用 dplyr 套件的 arrange() 函數來排序資料框,預設的排序方式均為遞增排序,如果希望調整為遞減排序,指定 arrange(desc()) 即可。

library(dplyr)

csv_url <- "https://storage.googleapis.com/learn_pd_like_tidyverse/gapminder.csv"
df <- read.csv(csv_url, stringsAsFactors = FALSE)
df %>% 
  arrange(year) %>%       # 依照 year 遞增排序
  head()
1
2
3
4
5
6
7
##       country continent year lifeExp      pop  gdpPercap
## 1 Afghanistan      Asia 1952  28.801  8425333   779.4453
## 2     Albania    Europe 1952  55.230  1282697  1601.0561
## 3     Algeria    Africa 1952  43.077  9279525  2449.0082
## 4      Angola    Africa 1952  30.015  4232095  3520.6103
## 5   Argentina  Americas 1952  62.485 17876956  5911.3151
## 6   Australia   Oceania 1952  69.120  8691212 10039.5956
1
2
3
4
5
6
7
library(dplyr)

csv_url <- "https://storage.googleapis.com/learn_pd_like_tidyverse/gapminder.csv"
df <- read.csv(csv_url, stringsAsFactors = FALSE)
df %>%
  arrange(desc(year)) %>% # 依照 year 遞減排序
  head()
1
2
3
4
5
6
7
##       country continent year lifeExp      pop  gdpPercap
## 1 Afghanistan      Asia 2007  43.828 31889923   974.5803
## 2     Albania    Europe 2007  76.423  3600523  5937.0295
## 3     Algeria    Africa 2007  72.301 33333216  6223.3675
## 4      Angola    Africa 2007  42.731 12420476  4797.2313
## 5   Argentina  Americas 2007  75.320 40301927 12779.3796
## 6   Australia   Oceania 2007  81.235 20434176 34435.3674
1
2
3
4
5
6
7

也能夠輸入多個變數排序,像是先依照 year 遞增排序再依照 continent 遞減排序。

library(dplyr)

csv_url <- "https://storage.googleapis.com/learn_pd_like_tidyverse/gapminder.csv"
df <- read.csv(csv_url, stringsAsFactors = FALSE)
df %>% 
  arrange(year, desc(continent)) %>%  # 先依照 year 遞增排序再依照 continent 遞減排序
  head()
1
2
3
4
5
6
7
##                  country continent year lifeExp     pop  gdpPercap
## 1              Australia   Oceania 1952   69.12 8691212 10039.5956
## 2            New Zealand   Oceania 1952   69.39 1994794 10556.5757
## 3                Albania    Europe 1952   55.23 1282697  1601.0561
## 4                Austria    Europe 1952   66.80 6927772  6137.0765
## 5                Belgium    Europe 1952   68.00 8730405  8343.1051
## 6 Bosnia and Herzegovina    Europe 1952   53.82 2791000   973.5332
1
2
3
4
5
6
7

新增變數

新增一個變數至現有的資料框中有兩種應用情景,一是計算衍生變數,二是非衍生變數,所謂衍生變數(Derived Variables)是指能夠透過現有變數生成的變數,以 1995 至 1996 年球季芝加哥公牛隊先發陣容的資料框為例,衍生變數可能是球員的姓 last_name,該變數可以從 player 衍生而得;非衍生變數可能是球員的身高,無法從既有變數中計算而得,新增非衍生變數時通常可以給一個值;或者給長度與列數相同的陣列。

Python

在 Python pandas 中我們可以使用 .map() 方法搭配 lambda 建立衍生變數:

import pandas as pd

numbers = [9, 23, 33, 91, 13]
players = ["Ron Harper", "Michael Jordan", "Scottie Pippen", "Dennis Rodman", "Luc Longley"]
df = pd.DataFrame()
df["number"] = numbers
df["player"] = players
df["last_name"] = df["player"].map(lambda x: x.split()[1])
df
1
2
3
4
5
6
7
8
9

使用 .map() 方法搭配 lambda 建立衍生變數 last_name

輸入一個值:隊伍名稱 "Chicago Bulls" ,或者輸入五個球員的身高:

import pandas as pd

numbers = [9, 23, 33, 91, 13]
players = ["Ron Harper", "Michael Jordan", "Scottie Pippen", "Dennis Rodman", "Luc Longley"]
df = pd.DataFrame()
df["number"] = numbers
df["player"] = players
df["team"] = "Chicago Bulls"
df["height"] = ["6-6", "6-6", "6-8", "6-7", "7-2"]
df
1
2
3
4
5
6
7
8
9
10

輸入一個值:隊伍名稱

R 語言

在 R 語言中可以透過 sapply() 函數實踐向量計算,將完成計算的向量直接指派回資料框中即可。

players <- c("Ron Harper", "Michael Jordan", "Scottie Pippen", "Dennis Rodman", "Luc Longley")
df <- data.frame(number = numbers, player = players, stringsAsFactors = FALSE)
get_last_name <- function(x) {
  split_lst <- strsplit(x, split = " ")
  name_length <- length(split_lst[[1]])
  last_name <- split_lst[[1]][name_length]
  return(last_name)
}
df$last_name <- sapply(df$player, FUN = get_last_name)
View(df)
1
2
3
4
5
6
7
8
9
10

透過 sapply() 函數實踐向量計算,將完成計算的向量直接指派回資料框中

輸入一個值:隊伍名稱 "Chicago Bulls" ,或者輸入五個球員的身高:

numbers <- c(9, 23, 33, 91, 13)
players <- c("Ron Harper", "Michael Jordan", "Scottie Pippen", "Dennis Rodman", "Luc Longley")
df <- data.frame(number = numbers, player = players, stringsAsFactors = FALSE)
df$team <- "Chicago Bulls"
df$height <- c("6-6", "6-6", "6-8", "6-7", "7-2")
View(df)
1
2
3
4
5
6

輸入一個值:隊伍名稱

也可以考慮使用 dplyr 套件的 mutate() 函數。

ibrary(dplyr)

numbers <- c(9, 23, 33, 91, 13)
players <- c("Ron Harper", "Michael Jordan", "Scottie Pippen", "Dennis Rodman", "Luc Longley")
df <- data.frame(number = numbers, player = players, stringsAsFactors = FALSE)
df %>% 
  mutate(
    team = "Chicago Bulls",
    height = c("6-6", "6-6", "6-8", "6-7", "7-2")
  )
1
2
3
4
5
6
7
8
9
10

使用 dplyr 套件的 mutate() 函數

新增觀測值

我推薦使用垂直合併資料框的方式來新增觀測值,如此可以避免變數型別轉換的問題,像是在 1995 至 1996 年球季芝加哥公牛隊先發陣容資料框中加入第六人 Toni Kukoc。

Python

在 Python pandas 中可以使用 df.append() 方法垂直合併資料框,合併完以後因為列索引值會重複,所以通常會再利用 reset_index() 方法重新設定列索引。

import pandas as pd

numbers = [9, 23, 33, 91, 13]
players = ["Ron Harper", "Michael Jordan", "Scottie Pippen", "Dennis Rodman", "Luc Longley"]
df = pd.DataFrame()
df["number"] = numbers
df["player"] = players
toni_kukoc = pd.DataFrame()
toni_kukoc["number"] = [7]
toni_kukoc["player"] = ["Toni Kukoc"]
df = df.append(toni_kukoc)
df = df.reset_index(drop=True) # 重新設定索引
df
1
2
3
4
5
6
7
8
9
10
11
12
13

在 1995 至 1996 年球季芝加哥公牛隊先發陣容資料框中加入第六人 Toni Kukoc

R 語言

在 R 語言中使用 rbind() 函數垂直合併資料框:

numbers <- c(9, 23, 33, 91, 13)
players <- c("Ron Harper", "Michael Jordan", "Scottie Pippen", "Dennis Rodman", "Luc Longley")
df <- data.frame(number = numbers, player = players, stringsAsFactors = FALSE)
toni_kukoc <- data.frame(number = 7, player = "Toni Kukoc", stringsAsFactors = FALSE)
df <- rbind(df, toni_kukoc)
View(df)
1
2
3
4
5
6

在 1995 至 1996 年球季芝加哥公牛隊先發陣容資料框中加入第六人 Toni Kukoc

摘要

Python 除了使用 .describe() 方法或是像 R 語言使用 summary() 函數可以獲取資料框的描述性統計,我們也能夠針對特定變數單獨摘要;例如計算 gapminder 資料框中 2007 年所有國家的人口總和。

Python

在 Python pandas 選擇資料框中特定變數會面對 Series 這樣的資料結構,而 Series 就有完整的摘要方法供我們呼叫,像總和、平均或中位數等。

import pandas as pd

csv_url = "https://storage.googleapis.com/learn_pd_like_tidyverse/gapminder.csv"
df = pd.read_csv(csv_url)
df[df.year == 2007]["pop"].sum()
1
2
3
4
5
## 6251013179
1

R 語言

在 R 語言可以使用 dplyr 套件的 summarise() 函數來做變數的摘要。

library(dplyr)

csv_url <- "https://storage.googleapis.com/learn_pd_like_tidyverse/gapminder.csv"
df <- read.csv(csv_url, stringsAsFactors = FALSE)
df %>% 
  filter(year == 2007) %>% 
  summarise(ttl_pop = sum(as.numeric(pop))) # integer 會溢位,轉換為 numeric
1
2
3
4
5
6
7
##      ttl_pop
## 1 6251013179
1
2

分組

除了單獨使用摘要的相關函數,我們也很常會需要利用相關的文字變數進行分組再摘要,例如計算 gapminder 資料框中 2007 年依照不同 continents 來摘要該洲所有國家的人口總和。

Python

在 Python pandas 中我們會使用 .groupby() 方法指定用來分組資料框的文字變數,然後針對變數呼叫摘要方法,分組摘要的結果會以 Series 的型別回傳。

import pandas as pd

csv_url = "https://storage.googleapis.com/learn_pd_like_tidyverse/gapminder.csv"
df = pd.read_csv(csv_url)
grouped = df[df.year == 2007].groupby("continent")
grouped["pop"].sum()
1
2
3
4
5
6
## continent
## Africa       929539692
## Americas     898871184
## Asia        3811953827
## Europe       586098529
## Oceania       24549947
## Name: pop, dtype: int64
1
2
3
4
5
6
7

.groupby() 方法中放多個文字變數就會形成兩層索引值的 Series 輸出,意即照多個文字變數分組,例如依照不同年份與 continents 來摘要各年各洲所有國家的人口總和(看後 10 筆即可)。

import pandas as pd

csv_url = "https://storage.googleapis.com/learn_pd_like_tidyverse/gapminder.csv"
df = pd.read_csv(csv_url)
grouped = df.groupby(["year", "continent"])
grouped["pop"].sum().tail(n = 10)
1
2
3
4
5
6
## year  continent
## 2002  Africa        833723916
##       Americas      849772762
##       Asia         3601802203
##       Europe        578223869
##       Oceania        23454829
## 2007  Africa        929539692
##       Americas      898871184
##       Asia         3811953827
##       Europe        586098529
##       Oceania        24549947
## Name: pop, dtype: int64
1
2
3
4
5
6
7
8
9
10
11
12

R 語言

在 R 語言我們利用 dplyr 套件的 group_by() 函數搭配 summarise() 函數來完成分組摘要,結果會以 data.frame 型別(tibble 型別近似 data.frame)回傳,例如計算 gapminder 資料框中 2007 年依照不同 continents 來摘要該洲所有國家的人口總和。

library(dplyr)

csv_url <- "https://storage.googleapis.com/learn_pd_like_tidyverse/gapminder.csv"
df <- read.csv(csv_url, stringsAsFactors = FALSE)
df %>% 
  filter(year == 2007) %>% 
  group_by(continent) %>% 
  summarise(ttl_pop = sum(as.numeric(pop))) # integer 會溢位,轉換為 numeric
1
2
3
4
5
6
7
8
## # A tibble: 5 x 2
##   continent    ttl_pop
##   <chr>          <dbl>
## 1 Africa     929539692
## 2 Americas   898871184
## 3 Asia      3811953827
## 4 Europe     586098529
## 5 Oceania     24549947
1
2
3
4
5
6
7
8

在 group_by() 函數中放多個文字變數即照多個文字變數分組,例如依照不同年份與 continents 來摘要各年各洲所有國家的人口總和(看後 10 筆即可)。

df %>% 
  group_by(year, continent) %>% 
  summarise(ttl_pop = sum(as.numeric(pop))) %>% # integer 會溢位,轉換為 numeric
  tail(10)
1
2
3
4
## # A tibble: 10 x 3
## # Groups:   year [2]
##     year continent    ttl_pop
##    <int> <chr>          <dbl>
##  1  2002 Africa     833723916
##  2  2002 Americas   849772762
##  3  2002 Asia      3601802203
##  4  2002 Europe     578223869
##  5  2002 Oceania     23454829
##  6  2007 Africa     929539692
##  7  2007 Americas   898871184
##  8  2007 Asia      3811953827
##  9  2007 Europe     586098529
## 10  2007 Oceania     24549947
1
2
3
4
5
6
7
8
9
10
11
12
13
14

小結

在這個小節中我們簡介 Python pandas 與 R 語言中的基本資料框操作技巧,包含建立、檢視、篩選、選擇、排序、新增變數、新增觀測值、摘要與分組。

延伸閱讀