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.
- 一些軟體包包含許多資料集。
構建您自己的資料幀
[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$var1 和 mydat2$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"。
有時我們需要在資料集中複製一些行。例如,如果我們想要生成一個具有 面板資料 結構的假資料集。在這種情況下,我們首先會生成時間不變變數,然後將每行按給定的標量複製以建立隨時間變化的變數。
可以使用 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]
- ↑ AER 包 http://cran.r-project.org/web/packages/AER/index.html
- ↑ EcDat 包 http://cran.r-project.org/web/packages/Ecdat/index.html
- ↑ “對英格蘭貧困變化原因的調查,主要是在最後兩個人口普查期間(第一部分)” - GU Yule - 《皇家統計學會雜誌》,1899 年 6 月,第 283 頁
- ↑ 使用 reshape 包重塑資料 : http://www.jstatsoft.org/v21/i12
- ↑ tables 包的示意:http://cran.r-project.org/web/packages/tables/vignettes/tables.pdf
- ↑ 合併資料幀,同時保留行
- ↑ R 資料手冊 http://cran.r-project.org/doc/manuals/R-data.html
- ↑ Paul Murrell 的 資料技術入門 http://www.stat.auckland.ac.nz/~paul/ItDT/
