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.
可以使用向量建立資料框。
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')
有多種方法可以檢查資料框,例如
- `str(df)` 提供資料的簡要描述
- `names(df)` 提供每個變數的名稱
- `summary(df)` 提供每個變數的一些基本摘要統計資訊
- `head(df)` 顯示前幾行
- `tail(df)` 顯示最後幾行。
- 可以使用 `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).
在處理資料框時,大多數情況下會更改資料,其中一項常見操作是新增列或行,從而增加資料框的維度。有多種方法可以實現,但最簡單的方法是 `cbind()` 和 `rbind()`,它們是 **base** 包的一部分。
mydata <- cbind(mydata, newVector)
mydata <- rbind(mydata, newVector)
請記住,newVector 的長度應與要附加其到的資料框一側的長度匹配。例如,在 `cbind()` 命令中,以下語句應為 TRUE
dim(mydata)[1]==length(newVector)
要檢視更多示例,可以隨時執行 `?base::cbind` 和 `?base::rbind`。
R 相比於 Stata 的一大優勢是可以同時處理多個數據集。只需要指定資料集名稱,並在每個變數名前面新增一個“$”符號(例如 `mydat1$var1` 和 `mydat2$var1`)。如果只處理一個數據集,並且不想每次都將資料集名稱作為字首新增到每個變數,可以使用 `attach()`。
mydata$var1
attach(mydata)
var1
detach(mydata)
在清理資料集時,經常需要檢查資料中是否存在重複的資訊。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
要建立新變數
mydata$newvar <- oldvar
如果要刪除資料集中某個變數,可以將 NULL 指定給該變數
# Delete the x variable in the df data frame.
df$x <- NULL
- 可以透過重新定義資料框的名稱向量來重新命名變數。
- **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)
可以使用 `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))
order()
mydat[order(var1,var2),]
假設要隨機化資料集中順序。只需要從均勻分佈生成一個向量,並根據該向量進行排序。
df[order(runif(nrow(df))),]
- `is.na()` 返回一個邏輯向量,如果資料集中任何變數缺失則為 TRUE,否則為 FALSE。
- `complete.cases()` 返回一個邏輯向量,如果所有情況都完整則為 TRUE,否則為 FALSE。
> table(complete.cases(df))
如果處理面板資料,則此主題很重要。 面板資料 可以儲存在寬格式中,每個單位一個觀測值,每個時間段一個變數;也可以儲存在長格式中,每個單位和時間段一個觀測值。`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”)合併“books”和“authors”表。我們使用merge()命令。我們指定第一個和第二個資料集的名稱,然後透過by.x和by.y指定兩個資料集中的識別符號。all.x和all.y指定是否要保留第一個和第二個資料集的所有觀察結果。在這種情況下,我們希望保留來自“books”資料集的所有觀察結果,但我們只保留與“books”資料集中的觀察結果匹配的來自“author”資料集的觀察結果。
> 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>
也可以合併兩個資料幀物件,同時保留兩個合併物件之一的行順序。[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/
