跳轉到內容

R 程式設計/資料框操作

來自華夏公益教科書

在本節中,我們將介紹用於讀取、管理和清理資料框的方法。

在 R 中,資料框是一個由相同長度的向量組成的列表。它們不需要是相同型別。例如,您可以在一個數據框中組合一個邏輯向量、一個字元向量和一個數值向量。

讀取和儲存資料

[編輯 | 編輯原始碼]

如果資料已處於 R 格式 (.Rda.Rdata),您可以使用 load() 將其載入到記憶體中。您可以使用 save() 將資料儲存到 R 格式。

load("mydata.Rda")
save(list='mydata',file="mydata.Rda")

示例資料集

[編輯 | 編輯原始碼]
  • 大多數軟體包都包含示例資料集來測試函式。
  • data() 函式不帶引數時會給出所有已載入軟體包中所有示例資料集的列表。
  • 如果您想將它們載入到記憶體中,您只需要使用 data 函式並將資料集的名稱作為引數。
  • str_data() (sfsmisc) 給出軟體包中所有資料集的結構。
> data() # lists all the datasets in all the packages in memory
> data(package="datasets") # lists all the datasets in the "datasets" package
> data(Orange) # loads the orange dataset in memory
> ?Orange # Help for the "Orange" Datasets
> str_data("datasets") # gives the structure of all the datasets in the datasets package.
  • 一些軟體包包含許多資料集。
    • datasets 軟體包
    • AER 軟體包 [1] 包含計量經濟學中一些重要教科書的複製資料集。
    • EcDat 軟體包 [2] 包含《應用計量經濟學雜誌》、《商業與經濟統計雜誌》等期刊的複製檔案。

構建您自己的資料幀

[edit | edit source]

您可以使用向量建立一個數據幀。

N <- 100
u <- rnorm(N)
x1 <- rnorm(N)
x2 <- rnorm(N)
y <- 1 + x1 + x2 + u
mydat <- data.frame(y,x1,x2)

R 擁有一個類似電子表格的資料編輯器。您可以使用它將資料輸入電子表格。

mydat <- edit(data.frame())

從剪貼簿讀取表格

> mydat <- read.table("clipboard")

您還可以使用 gsource() (Zelig) 在程式碼中讀取空格分隔的表格。以下是以 Yule 1899 資料為例。 [3]

mydat <- gsource(var.names = "id union pauperism out old  pop", 
variables = "
1 Kensington 27 5 104 136
2 Paddington  47 12 115 111
3 Fulham 31 21 85 174
")

您可以更改資料幀的列名。

c1 <- c('A','B','C')
c2 <- c('Alpha','Bravo','Charlie')
c3 <- c('1','2','3')
mydf <- data.frame(c1,c2,c3)
colnames(mydf) <- c('ColName1','ColName2','ColName3')

描述資料幀

[edit | edit source]

有各種方法可以檢查資料幀,例如

  • str(df) 給出資料非常簡短的描述
  • names(df) 給出每個變數的名稱
  • summary(df) 給出每個變數的一些非常基本 的彙總統計量
  • head(df) 顯示前幾行
  • tail(df) 顯示最後幾行。

瀏覽資料

[edit | edit source]
  • 您可以使用 View() 在電子表格中瀏覽資料。根據您的作業系統,此選項並非總是可用,結果也並非總是相同。
  • 您可以使用 head() 列印前幾行,使用 tail() 列印最後幾行。
View(mydata)
head(mydata, n = 20) # n = 20 means  that the first 20 lines are printed in the R console
  • RStudio 擁有一個不錯的 資料瀏覽器 (View(mydata))。
  • RKward 也擁有一個不錯的 資料瀏覽器
  • Paul Murrell 目前正在開發 rdataviewer 軟體包 (pdf).

繫結行或列

[edit | edit source]

在使用資料幀時,您通常會更改資料,並且可以對資料幀進行的一些更改之一是新增列或行,從而增加資料幀的維度。有幾種不同的方法可以做到這一點,但最簡單的方法是 cbind()rbind(),它們是 base 軟體包的一部分

mydata <- cbind(mydata, newVector)
mydata <- rbind(mydata, newVector)

請記住,newVector 的長度應與您要附加它的資料幀邊的長度匹配。例如,在 cbind() 命令中,以下語句應為 TRUE

dim(mydata)[1]==length(newVector)

要檢視更多示例,您始終可以執行 ?base::cbind?base::rbind

附加資料

[edit | edit source]

R 相對於 Stata 的一大優勢是您可以同時處理多個數據集。您只需要指定資料集的名稱,並在每個變數名稱之前加上“$”符號 (例如 mydat1$var1mydat2$var1)。如果您只使用一個數據集,並且不想為每個變數重複寫資料集名稱作為字首,您可以使用 attach()

mydata$var1
attach(mydata)
var1
detach(mydata)

檢測重複項

[edit | edit source]

當您想要清理資料集時,檢查資料中是否存在相同的資訊通常很有用。R 提供了一些函式來檢測重複項。

  • duplicated() 檢視重複元素並返回一個邏輯向量。您可以使用 table() 來彙總此向量。
  • Duplicated() (sfsmisc) 對此命令進行了概括。Duplicated() 只用 “NA” 標記唯一值。
  • remove.dup.rows() (cwhmisc).
  • unique() 只保留資料集中唯一的行。
  • distinct() (dplyr) 只保留資料集中唯一的/不同的行。


library("Zelig")
mydat <- gsource(
variables = "
1 1 1 1
1 1 1 1
1 2 3 4
1 2 3 4
1 2 2 2
1 2 3 2")
unique(mydat) # keep unique rows
library(cwhmisc)
remove.dup.rows(mydat) # similar to unique()
table(duplicated(mydat)) # table duplicated lines
mydat$dups <- duplicated(mydat) # add a logical variable for duplicates

建立和刪除變數

[edit | edit source]

要建立一個新變數

mydata$newvar <- oldvar

如果您想要刪除資料集中某個變數,可以將 NULL 分配給該變數

# Delete the x variable in the df data frame.
df$x <- NULL

重新命名變數

[edit | edit source]
  • 可以透過重新定義資料幀的名稱向量來重新命名變數。
  • reshape 軟體包中還有一個 rename() 函式。
df <- data.frame(x = 1:10, y = 21:30)
names(df)
names(df) <- c("toto","tata")
names(df)
names(df)[2] <- "titi"
names(df)

建立資料的子集

[edit | edit source]

可以使用 subset() 對資料進行子集化。第一個引數是資料集的名稱,第二個引數是一個邏輯條件,用於說明哪些行將包含在新資料集中,最後一個引數是將包含在新資料集中 的變數列表。

在以下示例中,我們生成了一個假資料集,並使用 subset() 命令選擇感興趣的行和列。我們選擇 x1 > 0 且 x2 < 0 的行,並且只保留 x1 和 x2 作為變數。

N <- 100
x1 <- rnorm(N)
x2 <- 1 + rnorm(N) + x1
x3 <- rnorm(N) + x2
mydat <- data.frame(x1,x2,x3)
subset(x = mydat, subset = x1 > 0 & x2 < 0, select = c(x1,x2))
subset(x = mydat, subset = x1 > 0 & x2 < 0, select = - x3) # the same.

也可以使用 select 選項重新排序列。

subset(x = mydat, subset = x1 > 0 & x2 < 0, select = c(x1,x2))
subset(x = mydat, subset = x1 > 0 & x2 < 0, select = c(x2,x1))

排序和排列

[edit | edit source]
  • order()
mydat[order(var1,var2),]

假設您想隨機化資料集中 的順序。您只需要從均勻分佈中生成一個向量,並按照該向量進行排序。

df[order(runif(nrow(df))),]

檢測缺失值

[edit | edit source]
  • is.na() 返回一個邏輯向量,如果資料集中 的任何變數都缺失,則等於 TRUE,否則等於 FALSE。
  • complete.cases() 返回一個邏輯向量,如果所有案例都完整,則表示 TRUE,否則表示 FALSE。
> table(complete.cases(df))

重塑資料幀

[edit | edit source]

如果您處理面板資料,這個主題很重要。 面板資料 可以以寬格式儲存,每個單元一個觀測值,每個時間段一個變數,也可以以長格式儲存,每個單元和時間段一個觀測值。reshape() 將資料集重塑為寬格式或長格式。

> country <- c("'Angola'","'UK'","'France'")
> gdp.1960 <- c(1,2,3)
> gdp.1970 <- c(2,4,6)
> mydat <- data.frame(country,gdp.1960,gdp.1970)
> mydat # wide format
  country gdp.1960 gdp.1970
1  Angola       1       2
2      UK       2       4
3  France       3       6
> reshape( data = mydat, varying = list(2:3) , v.names = "gdp", direction = "long") # long format
    country time gdp id
1.1  Angola    1   1  1
2.1      UK    1   2  2
3.1  France    1   3  3
1.2  Angola    2   2  1
2.2      UK    2   4  2
3.2  France    2   6  3
  • varying 給出隨時間變化的列的編號
  • v.names 給出隨時間變化的變數的字首
  • direction 給出方向,要麼是 "long",要麼是 "wide"。
  • 另請參閱 
    • reShape() (Hmisc)
    • 參見 Hadley Wickham 的 reshape[4]
    • 參見 Duncan Murdoch 的 tables[5]
[編輯 | 編輯原始碼]

擴充套件資料集

[編輯 | 編輯原始碼]

有時我們需要在資料集中複製一些行。例如,如果我們想要生成一個具有 面板資料 結構的假資料集。在這種情況下,我們首先會生成時間不變變數,然後將每行按給定的標量複製以建立隨時間變化的變數。

可以使用 epicalc 包中的 expand() 函式(由於該包不再存在,因此在 [1] 中給出了擴充套件選項)。這將把每行乘以給定的數字。

N <- 1000
T <- 5
wide <- data.frame(id = 1:N,f = rnorm(N),  rep = T)
library("epicalc")
long <- expand(wide,index.var = "rep")
long$time <- rep(1:T,N)

我們也可以使用“自己動手解決方案”或建立自己的函式。想法很簡單。我們建立一個向量,該向量為每行給出應複製的次數(在下面的示例中為 dups)。然後,我們使用 rep() 函式建立一個向量,該向量根據我們的需要重複行號。最後一步建立一個新資料集,該資料集根據所需模式重複行。

expand <- function(df,dups){
	df$dups <- dups
	pattern <- rep(1:nrow(df), times=df$dups)
	df2 <- df[pattern,]
	index <- function(x){
		1:length(x)
		}
	df2$year <- unlist(tapply(df2$dups, df2$id, index))
	df2$dups <- NULL 
	return(df2)
	}

df <- data.frame(x = rnorm(3), id = 1:3)
dups = c(3,1,2)
expand(df,dups)

合併資料幀

[編輯 | 編輯原始碼]

合併資料可能會非常混亂,尤其是在多次合併的情況下。這是一個簡單的例子 

我們有一個描述作者的表格 

> authors <- data.frame(
+     surname = I(c("Tukey", "Venables", "Tierney", "Ripley", "McNeil")),
+     nationality = c("US", "Australia", "US", "UK", "Australia"),
+     deceased = c("yes", rep("no", 4)))
> authors
   surname nationality deceased
1    Tukey          US      yes
2 Venables   Australia       no
3  Tierney          US       no
4   Ripley          UK       no
5   McNeil   Australia       no

還有一個描述書籍的表格

> books <- data.frame(
+     name = I(c("Tukey", "Venables", "Tierney",
+              "Ripley", "Ripley", "McNeil", "R Core")),
+     title = c("Exploratory Data Analysis",
+               "Modern Applied Statistics ...",
+               "LISP-STAT",
+               "Spatial Statistics", "Stochastic Simulation",
+               "Interactive Data Analysis",
+               "An Introduction to R"),
+     other.author = c(NA, "Ripley", NA, NA, NA, NA,
+                      "Venables & Smith"))
> books
      name                         title     other.author
1    Tukey     Exploratory Data Analysis             <NA>
2 Venables Modern Applied Statistics ...           Ripley
3  Tierney                     LISP-STAT             <NA>
4   Ripley            Spatial Statistics             <NA>
5   Ripley         Stochastic Simulation             <NA>
6   McNeil     Interactive Data Analysis             <NA>
7   R Core          An Introduction to R Venables & Smith

我們想根據作者姓名(第一個資料集中為“surname”,第二個資料集中為“name”)將書籍和作者表格合併。我們使用 merge() 命令。我們指定第一個和第二個資料集的名稱,然後使用 by.x 和 by.y 指定兩個資料集中的識別符號。all.x 和 all.y 指定我們是否要保留第一個和第二個資料集的所有觀測值。在這種情況下,我們希望擁有書籍資料集的所有觀測值,但只保留與書籍資料集中觀測值匹配的作者資料集的觀測值。

> final <- merge(books, authors, by.x = "name", by.y = "surname", sort=F,all.x=T,all.y=F)
> final
      name                         title     other.author nationality deceased
1    Tukey     Exploratory Data Analysis             <NA>          US      yes
2 Venables Modern Applied Statistics ...           Ripley   Australia       no
3  Tierney                     LISP-STAT             <NA>          US       no
4   Ripley            Spatial Statistics             <NA>          UK       no
5   Ripley         Stochastic Simulation             <NA>          UK       no
6   McNeil     Interactive Data Analysis             <NA>   Australia       no
7   R Core          An Introduction to R Venables & Smith        <NA>     <NA>

也可以合併兩個 data.frame 物件,同時保留其中一個合併物件的行的順序。[6]

參考資料

[編輯 | 編輯原始碼]
  1. AER 包 http://cran.r-project.org/web/packages/AER/index.html
  2. EcDat 包 http://cran.r-project.org/web/packages/Ecdat/index.html
  3. “對英格蘭貧困變化原因的調查,主要是在最後兩個人口普查期間(第一部分)” - GU Yule - 《皇家統計學會雜誌》,1899 年 6 月,第 283 頁
  4. 使用 reshape 包重塑資料 : http://www.jstatsoft.org/v21/i12
  5. tables 包的示意:http://cran.r-project.org/web/packages/tables/vignettes/tables.pdf
  6. 合併資料幀,同時保留行
  7. R 資料手冊 http://cran.r-project.org/doc/manuals/R-data.html
  8. Paul Murrell 的 資料技術入門 http://www.stat.auckland.ac.nz/~paul/ItDT/


前一個:隨機數生成 索引 下一個:匯入和匯出資料
華夏公益教科書