跳转到内容

R 编程/数据框操作

来自 Wikibooks,开放世界中的开放书籍

在本节中,我们将介绍如何读取、管理和清理数据框的方法。

在 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] 包含《应用计量经济学杂志》、《商业与经济统计学杂志》等的复制档案。

构建您自己的数据框

[编辑 | 编辑源代码]

可以使用向量创建数据框。

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”。
  • 另请参阅
    • `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”)合并“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]

参考文献

[编辑 | 编辑源代码]
  1. AER 包 https://cran.r-project.org.cn/web/packages/AER/index.html
  2. EcDat 包 https://cran.r-project.org.cn/web/packages/Ecdat/index.html
  3. “对英国贫困变化原因的调查,主要是在过去两个人口普查之间十年(第一部分)” - GU Yule - 英国皇家统计学会杂志,1899 年 6 月,第 283 页
  4. 使用 reshape 包重塑数据:http://www.jstatsoft.org/v21/i12
  5. tables 包的说明:https://cran.r-project.org.cn/web/packages/tables/vignettes/tables.pdf
  6. 合并数据帧同时保留行顺序
  7. R 数据手册 https://cran.r-project.org.cn/doc/manuals/R-data.html
  8. Paul Murrell 数据技术入门 http://www.stat.auckland.ac.nz/~paul/ItDT/


前一页:随机数生成 索引 下一页:导入和导出数据
华夏公益教科书