重新编码列表中的变量
Recoding variables in a list
我想我是本着 "no question is too easy" 的精神写作的,我只是一个普通的 Stata 用户社会科学家,第一次接触 R 并且面对它度过了无尽的夜晚......请怜悯!
我正在使用来自 20 个国家/地区的比较数据集(大约 20,000 个观察值,各国之间相当均衡)。
我必须执行一组计算量相当大的 MCMC 模拟,因此我决定将 df 拆分为包含 20 个(特定国家/地区)df 的列表,然后继续 lapply()
。 (我读到在 R 上避免 for
循环更有效,对吧?)
我最直接的问题是我无法预处理列表中包含的各种 df 中的元素。特别是,我必须重新编码一组 15 个变量,这些变量是 0 到 10 之间的整数,包括 SPSS 缺失案例的典型值:77 88, 89, 99, 999
。我想将这些值重新编码为 NA
,然后做一些额外的小变换:以 0 为中心,用两组不同的变量定义两个 df 对象 T
和 TT
,稍后在模拟。必须在构成 "master" 列表 "ees2009split".
的 20 个不同国家/地区特定列表元素中重复此任务
ees2009split <- vector("list", 20)
ees2009split <- split(ees2009, ees2009$t102) # t102 is the country identifier
names(ees2009split) <- country.names[1:2] # rename list objects with country names
这是我的列表(抱歉,我无法提供可重现的示例):
> str(ees2009split)
List of 20
$ Austria :'data.frame': 1000 obs. of 17 variables:
..$ t102 : int [1:1000] 1040 1040 1040 1040 1040 1040 1040 1040 1040 1040 ...
..$ q46 : int [1:1000] 77 2 5 5 5 77 5 5 5 77 ...
..$ q47_p1 : int [1:1000] 77 3 5 4 77 77 5 1 89 77 ...
..$ q47_p2 : int [1:1000] 77 8 7 6 77 77 5 6 5 77 ...
..$ q47_p3 : int [1:1000] 77 10 10 9 77 77 5 7 7 77 ...
..$ q47_p4 : int [1:1000] 77 10 9 8 77 77 5 7 4 77 ...
..$ q47_p5 : int [1:1000] 77 2 5 3 77 77 5 1 3 77 ...
..$ q47_p6 : int [1:1000] 77 4 89 5 77 77 89 2 89 77 ...
..$ q47_p7 : int [1:1000] 77 3 89 6 77 77 89 3 5 77 ...
..$ q47_p8 : int [1:1000] 77 1 0 0 77 77 5 0 89 77 ...
..$ q47_p9 : int [1:1000] 99 99 99 99 99 99 99 99 99 99 ...
..$ q47_p10: int [1:1000] 99 99 99 99 99 99 99 99 99 99 ...
..$ q47_p11: int [1:1000] 99 99 99 99 99 99 99 99 99 99 ...
..$ q47_p12: int [1:1000] 99 99 99 99 99 99 99 99 99 99 ...
..$ q47_p13: int [1:1000] 99 99 99 99 99 99 99 99 99 99 ...
..$ q47_p14: int [1:1000] 99 99 99 99 99 99 99 99 99 99 ...
..$ q47_p15: int [1:1000] 99 99 99 99 99 99 99 99 99 99 ...
$ Belgium :'data.frame': 1002 obs. of 17 variables:
..$ t102 : int [1:1002] 1056 1056 1056 1056 1056 1056 1056 1056 1056 1056 ...
..$ q46 : int [1:1002] 5 0 77 88 77 88 5 2 77 5 ...
..$ q47_p1 : int [1:1002] 88 5 77 77 6 77 5 77 5 77 ...
..$ q47_p2 : int [1:1002] 88 10 77 77 8 77 89 77 10 77 ...
..$ q47_p3 : int [1:1002] 88 7 77 77 5 77 3 77 0 77 ...
..$ q47_p4 : int [1:1002] 88 10 77 77 10 77 10 77 10 77 ...
..$ q47_p5 : int [1:1002] 88 0 77 77 4 77 4 77 5 77 ...
..$ q47_p6 : int [1:1002] 99 99 77 99 99 77 99 77 99 99 ...
..$ q47_p7 : int [1:1002] 99 99 77 99 99 77 99 77 99 99 ...
..$ q47_p8 : int [1:1002] 99 99 88 99 99 77 99 77 99 99 ...
..$ q47_p9 : int [1:1002] 99 99 77 99 99 77 99 77 99 99 ...
..$ q47_p10: int [1:1002] 99 99 99 99 99 99 99 99 99 99 ...
..$ q47_p11: int [1:1002] 99 99 99 99 99 99 99 99 99 99 ...
..$ q47_p12: int [1:1002] 99 99 99 99 99 99 99 99 99 99 ...
..$ q47_p13: int [1:1002] 99 99 99 99 99 99 99 99 99 99 ...
..$ q47_p14: int [1:1002] 99 99 99 99 99 99 99 99 99 99 ...
..$ q47_p15: int [1:1002] 99 99 99 99 99 99 99 99 99 99 ...
等等...直到国家 20。
我定义了两个要用 lapply()
调用的函数,函数 rename()
和 recode()
:
rename <- function(x) {
# renaming
names(x) <- gsub("q46", "lr.self", names(x))
names(x) <- gsub("q47_p", "lr.p", names(x))
return(x)
}
到目前为止一切顺利:
> processed.dat <- lapply(ees2009split, renaming)
> str(processed.dat)
List of 20
$ Austria :'data.frame': 1000 obs. of 17 variables:
..$ t102 : int [1:1000] 1040 1040 1040 1040 1040 1040 1040 1040 1040 1040 ...
..$ lr.self: int [1:1000] 77 2 5 5 5 77 5 5 5 77 ...
..$ lr.p1 : int [1:1000] 77 3 5 4 77 77 5 1 89 77 ...
# I omit the rest...
有了重新编码功能,我反而很辛苦:
recoding <- function(x){
# recode missing values
x$lr.self[lr.self %in% c(77, 88, 89, 98, 99, 999)] <- NA
x$lr.p1[lr.p1 %in% c(77, 88, 89, 98, 99, 999)] <- NA
x$lr.p2[lr.p2 %in% c(77, 88, 89, 98, 99, 999)] <- NA
x$lr.p3[lr.p3 %in% c(77, 88, 89, 98, 99, 999)] <- NA
x$lr.p4[lr.p4 %in% c(77, 88, 89, 98, 99, 999)] <- NA
x$lr.p5[lr.p5 %in% c(77, 88, 89, 98, 99, 999)] <- NA
x$lr.p6[lr.p6 %in% c(77, 88, 89, 98, 99, 999)] <- NA
x$lr.p7[lr.p7 %in% c(77, 88, 89, 98, 99, 999)] <- NA
x$lr.p8[lr.p8 %in% c(77, 88, 89, 98, 99, 999)] <- NA
x$lr.p9[lr.p9 %in% c(77, 88, 89, 98, 99, 999)] <- NA
x$lr.p10[lr.p10 %in% c(77, 88, 89, 98, 99, 999)] <- NA
x$lr.p11[lr.p11 %in% c(77, 88, 89, 98, 99, 999)] <- NA
x$lr.p12[lr.p12 %in% c(77, 88, 89, 98, 99, 999)] <- NA
x$lr.p13[lr.p13 %in% c(77, 88, 89, 98, 99, 999)] <- NA
x$lr.p14[lr.p14 %in% c(77, 88, 89, 98, 99, 999)] <- NA
x$lr.p15[lr.p15 %in% c(77, 88, 89, 98, 99, 999)] <- NA
x$T <- cbind(lr.self, lr.p1, lr.p2, lr.p3, lr.p4, lr.p5, lr.p6, lr.p7, lr.p8, lr.p9, lr.p10, lr.p11, lr.p12, lr.p13, lr.p14, lr.p15)
T <- T - 5 # centering on 0
lrself.resc <- T[,1] # rescaled lr.self
TT <- T[,-1] # whole matrix rescaled
N <- nrow(TT)
q <- ncol(TT)
z <- TT
x$dat.list <- list(lr.self=lr.self, lr.p1=lr.p1, lr.p2=lr.p2, lr.p3=lr.p3, lr.p4=lr.p4, lr.p5=lr.p5, lr.p6=lr.p6, lr.p7=lr.p7, lr.p8=lr.p8, lr.p9=lr.p9, lr.p10=lr.p10, lr.p11=lr.p11, lr.p12=lr.p12, lr.p13=lr.p13, lr.p14=lr.p14, lr.p15=lr.p15, T=T, TT=TT, lrself.resc, N=N, q=q, z=z)
return(x$dat.list)
}
这是输出:
> processed.dat <- lapply(ees2009split, recoding)
Error in match(x, table, nomatch = 0L) : object 'lr.self' not found
Called from: FUN(X[[1L]], ...)
Browse[1]>
1) 我应该如何重新编码包含在 lapply()
列表中的数据框中的变量?更广泛地说,如何在函数内的国家/地区 df 内插入对象?
2)从更一般的立场来看,这种处理方式是否正确?拆分,定义task-specific函数,用lapply()
调用,最后重新组合?
感谢您提出任何建议或意见。
安德里亚
这应该是为了数据清理。我使用库 gdata
,您可能必须使用此命令安装它:install.packages('gdata')
。在其中你会发现一个最有用的函数,即unknownToNA()
。请参见下面的示例。
正如我所说,我更喜欢在拆分数据之前进行清理。我也冒昧地使用了 EES 2009 dataset:
library(foreign)
library(gdata)
#setwd("/Data/sample")
#list.files()
mydata <- read.dta("ZA5055_v1-1-0.dta")
keepvars <- grep("^q46|^q47|^t102",names(mydata), value=T)
mydata2 <- subset(mydata, select=keepvars)
rm(mydata)
str(mydata2)
head(mydata2)
naval <- c(77, 88, 89, 99, 999)
mydata3 <- unknownToNA(mydata2, unknown=list(.default=naval))
head(mydata3)
# t102 q46 q47_p1 q47_p2 q47_p3 q47_p4 q47_p5 q47_p6 q47_p7 q47_p8 q47_p9 q47_p10 q47_p11 q47_p12 q47_p13
# 1 Austria NA NA NA NA NA NA NA NA NA NA NA NA NA NA
# 2 Austria 2 3 8 10 10 2 4 3 1 NA NA NA NA NA
# 3 Austria 5 5 7 10 9 5 NA NA 0 NA NA NA NA NA
# 4 Austria 5 4 6 9 8 3 5 6 0 NA NA NA NA NA
# 5 Austria 5 NA NA NA NA NA NA NA NA NA NA NA NA NA
# 6 Austria NA NA NA NA NA NA NA NA NA NA NA NA NA NA
# q47_p14 q47_p15
# 1 NA NA
# 2 NA NA
# 3 NA NA
# 4 NA NA
# 5 NA NA
# 6 NA NA
如果您出于某种原因更愿意先拆分,请开始:
library(gdata)
ees2009split <- split(mydata2, mydata2$t102)
ees2009split <- unknownToNA(ees2009split, unknown=list(.default=list(naval)))
head(ees2009split[[1]])
t102 q46 q47_p1 q47_p2 q47_p3 q47_p4 q47_p5 q47_p6 q47_p7 q47_p8 q47_p9 q47_p10 q47_p11 q47_p12 q47_p13
1 Austria NA NA NA NA NA NA NA NA NA NA NA NA NA NA
2 Austria 2 3 8 10 10 2 4 3 1 NA NA NA NA NA
3 Austria 5 5 7 10 9 5 NA NA 0 NA NA NA NA NA
4 Austria 5 4 6 9 8 3 5 6 0 NA NA NA NA NA
5 Austria 5 NA NA NA NA NA NA NA NA NA NA NA NA NA
6 Austria NA NA NA NA NA NA NA NA NA NA NA NA NA NA
q47_p14 q47_p15
1 NA NA
2 NA NA
3 NA NA
4 NA NA
5 NA NA
6 NA NA
恐怕我对你的后续步骤了解不够,无法提供进一步帮助。
但通常为了缩放我使用 scale
函数,它以 0 为中心并归一化:
head(scale(mydata3[,-1]))
我想我是本着 "no question is too easy" 的精神写作的,我只是一个普通的 Stata 用户社会科学家,第一次接触 R 并且面对它度过了无尽的夜晚......请怜悯!
我正在使用来自 20 个国家/地区的比较数据集(大约 20,000 个观察值,各国之间相当均衡)。
我必须执行一组计算量相当大的 MCMC 模拟,因此我决定将 df 拆分为包含 20 个(特定国家/地区)df 的列表,然后继续 lapply()
。 (我读到在 R 上避免 for
循环更有效,对吧?)
我最直接的问题是我无法预处理列表中包含的各种 df 中的元素。特别是,我必须重新编码一组 15 个变量,这些变量是 0 到 10 之间的整数,包括 SPSS 缺失案例的典型值:77 88, 89, 99, 999
。我想将这些值重新编码为 NA
,然后做一些额外的小变换:以 0 为中心,用两组不同的变量定义两个 df 对象 T
和 TT
,稍后在模拟。必须在构成 "master" 列表 "ees2009split".
ees2009split <- vector("list", 20)
ees2009split <- split(ees2009, ees2009$t102) # t102 is the country identifier
names(ees2009split) <- country.names[1:2] # rename list objects with country names
这是我的列表(抱歉,我无法提供可重现的示例):
> str(ees2009split)
List of 20
$ Austria :'data.frame': 1000 obs. of 17 variables:
..$ t102 : int [1:1000] 1040 1040 1040 1040 1040 1040 1040 1040 1040 1040 ...
..$ q46 : int [1:1000] 77 2 5 5 5 77 5 5 5 77 ...
..$ q47_p1 : int [1:1000] 77 3 5 4 77 77 5 1 89 77 ...
..$ q47_p2 : int [1:1000] 77 8 7 6 77 77 5 6 5 77 ...
..$ q47_p3 : int [1:1000] 77 10 10 9 77 77 5 7 7 77 ...
..$ q47_p4 : int [1:1000] 77 10 9 8 77 77 5 7 4 77 ...
..$ q47_p5 : int [1:1000] 77 2 5 3 77 77 5 1 3 77 ...
..$ q47_p6 : int [1:1000] 77 4 89 5 77 77 89 2 89 77 ...
..$ q47_p7 : int [1:1000] 77 3 89 6 77 77 89 3 5 77 ...
..$ q47_p8 : int [1:1000] 77 1 0 0 77 77 5 0 89 77 ...
..$ q47_p9 : int [1:1000] 99 99 99 99 99 99 99 99 99 99 ...
..$ q47_p10: int [1:1000] 99 99 99 99 99 99 99 99 99 99 ...
..$ q47_p11: int [1:1000] 99 99 99 99 99 99 99 99 99 99 ...
..$ q47_p12: int [1:1000] 99 99 99 99 99 99 99 99 99 99 ...
..$ q47_p13: int [1:1000] 99 99 99 99 99 99 99 99 99 99 ...
..$ q47_p14: int [1:1000] 99 99 99 99 99 99 99 99 99 99 ...
..$ q47_p15: int [1:1000] 99 99 99 99 99 99 99 99 99 99 ...
$ Belgium :'data.frame': 1002 obs. of 17 variables:
..$ t102 : int [1:1002] 1056 1056 1056 1056 1056 1056 1056 1056 1056 1056 ...
..$ q46 : int [1:1002] 5 0 77 88 77 88 5 2 77 5 ...
..$ q47_p1 : int [1:1002] 88 5 77 77 6 77 5 77 5 77 ...
..$ q47_p2 : int [1:1002] 88 10 77 77 8 77 89 77 10 77 ...
..$ q47_p3 : int [1:1002] 88 7 77 77 5 77 3 77 0 77 ...
..$ q47_p4 : int [1:1002] 88 10 77 77 10 77 10 77 10 77 ...
..$ q47_p5 : int [1:1002] 88 0 77 77 4 77 4 77 5 77 ...
..$ q47_p6 : int [1:1002] 99 99 77 99 99 77 99 77 99 99 ...
..$ q47_p7 : int [1:1002] 99 99 77 99 99 77 99 77 99 99 ...
..$ q47_p8 : int [1:1002] 99 99 88 99 99 77 99 77 99 99 ...
..$ q47_p9 : int [1:1002] 99 99 77 99 99 77 99 77 99 99 ...
..$ q47_p10: int [1:1002] 99 99 99 99 99 99 99 99 99 99 ...
..$ q47_p11: int [1:1002] 99 99 99 99 99 99 99 99 99 99 ...
..$ q47_p12: int [1:1002] 99 99 99 99 99 99 99 99 99 99 ...
..$ q47_p13: int [1:1002] 99 99 99 99 99 99 99 99 99 99 ...
..$ q47_p14: int [1:1002] 99 99 99 99 99 99 99 99 99 99 ...
..$ q47_p15: int [1:1002] 99 99 99 99 99 99 99 99 99 99 ...
等等...直到国家 20。
我定义了两个要用 lapply()
调用的函数,函数 rename()
和 recode()
:
rename <- function(x) {
# renaming
names(x) <- gsub("q46", "lr.self", names(x))
names(x) <- gsub("q47_p", "lr.p", names(x))
return(x)
}
到目前为止一切顺利:
> processed.dat <- lapply(ees2009split, renaming)
> str(processed.dat)
List of 20
$ Austria :'data.frame': 1000 obs. of 17 variables:
..$ t102 : int [1:1000] 1040 1040 1040 1040 1040 1040 1040 1040 1040 1040 ...
..$ lr.self: int [1:1000] 77 2 5 5 5 77 5 5 5 77 ...
..$ lr.p1 : int [1:1000] 77 3 5 4 77 77 5 1 89 77 ...
# I omit the rest...
有了重新编码功能,我反而很辛苦:
recoding <- function(x){
# recode missing values
x$lr.self[lr.self %in% c(77, 88, 89, 98, 99, 999)] <- NA
x$lr.p1[lr.p1 %in% c(77, 88, 89, 98, 99, 999)] <- NA
x$lr.p2[lr.p2 %in% c(77, 88, 89, 98, 99, 999)] <- NA
x$lr.p3[lr.p3 %in% c(77, 88, 89, 98, 99, 999)] <- NA
x$lr.p4[lr.p4 %in% c(77, 88, 89, 98, 99, 999)] <- NA
x$lr.p5[lr.p5 %in% c(77, 88, 89, 98, 99, 999)] <- NA
x$lr.p6[lr.p6 %in% c(77, 88, 89, 98, 99, 999)] <- NA
x$lr.p7[lr.p7 %in% c(77, 88, 89, 98, 99, 999)] <- NA
x$lr.p8[lr.p8 %in% c(77, 88, 89, 98, 99, 999)] <- NA
x$lr.p9[lr.p9 %in% c(77, 88, 89, 98, 99, 999)] <- NA
x$lr.p10[lr.p10 %in% c(77, 88, 89, 98, 99, 999)] <- NA
x$lr.p11[lr.p11 %in% c(77, 88, 89, 98, 99, 999)] <- NA
x$lr.p12[lr.p12 %in% c(77, 88, 89, 98, 99, 999)] <- NA
x$lr.p13[lr.p13 %in% c(77, 88, 89, 98, 99, 999)] <- NA
x$lr.p14[lr.p14 %in% c(77, 88, 89, 98, 99, 999)] <- NA
x$lr.p15[lr.p15 %in% c(77, 88, 89, 98, 99, 999)] <- NA
x$T <- cbind(lr.self, lr.p1, lr.p2, lr.p3, lr.p4, lr.p5, lr.p6, lr.p7, lr.p8, lr.p9, lr.p10, lr.p11, lr.p12, lr.p13, lr.p14, lr.p15)
T <- T - 5 # centering on 0
lrself.resc <- T[,1] # rescaled lr.self
TT <- T[,-1] # whole matrix rescaled
N <- nrow(TT)
q <- ncol(TT)
z <- TT
x$dat.list <- list(lr.self=lr.self, lr.p1=lr.p1, lr.p2=lr.p2, lr.p3=lr.p3, lr.p4=lr.p4, lr.p5=lr.p5, lr.p6=lr.p6, lr.p7=lr.p7, lr.p8=lr.p8, lr.p9=lr.p9, lr.p10=lr.p10, lr.p11=lr.p11, lr.p12=lr.p12, lr.p13=lr.p13, lr.p14=lr.p14, lr.p15=lr.p15, T=T, TT=TT, lrself.resc, N=N, q=q, z=z)
return(x$dat.list)
}
这是输出:
> processed.dat <- lapply(ees2009split, recoding)
Error in match(x, table, nomatch = 0L) : object 'lr.self' not found
Called from: FUN(X[[1L]], ...)
Browse[1]>
1) 我应该如何重新编码包含在 lapply()
列表中的数据框中的变量?更广泛地说,如何在函数内的国家/地区 df 内插入对象?
2)从更一般的立场来看,这种处理方式是否正确?拆分,定义task-specific函数,用lapply()
调用,最后重新组合?
感谢您提出任何建议或意见。 安德里亚
这应该是为了数据清理。我使用库 gdata
,您可能必须使用此命令安装它:install.packages('gdata')
。在其中你会发现一个最有用的函数,即unknownToNA()
。请参见下面的示例。
正如我所说,我更喜欢在拆分数据之前进行清理。我也冒昧地使用了 EES 2009 dataset:
library(foreign)
library(gdata)
#setwd("/Data/sample")
#list.files()
mydata <- read.dta("ZA5055_v1-1-0.dta")
keepvars <- grep("^q46|^q47|^t102",names(mydata), value=T)
mydata2 <- subset(mydata, select=keepvars)
rm(mydata)
str(mydata2)
head(mydata2)
naval <- c(77, 88, 89, 99, 999)
mydata3 <- unknownToNA(mydata2, unknown=list(.default=naval))
head(mydata3)
# t102 q46 q47_p1 q47_p2 q47_p3 q47_p4 q47_p5 q47_p6 q47_p7 q47_p8 q47_p9 q47_p10 q47_p11 q47_p12 q47_p13
# 1 Austria NA NA NA NA NA NA NA NA NA NA NA NA NA NA
# 2 Austria 2 3 8 10 10 2 4 3 1 NA NA NA NA NA
# 3 Austria 5 5 7 10 9 5 NA NA 0 NA NA NA NA NA
# 4 Austria 5 4 6 9 8 3 5 6 0 NA NA NA NA NA
# 5 Austria 5 NA NA NA NA NA NA NA NA NA NA NA NA NA
# 6 Austria NA NA NA NA NA NA NA NA NA NA NA NA NA NA
# q47_p14 q47_p15
# 1 NA NA
# 2 NA NA
# 3 NA NA
# 4 NA NA
# 5 NA NA
# 6 NA NA
如果您出于某种原因更愿意先拆分,请开始:
library(gdata)
ees2009split <- split(mydata2, mydata2$t102)
ees2009split <- unknownToNA(ees2009split, unknown=list(.default=list(naval)))
head(ees2009split[[1]])
t102 q46 q47_p1 q47_p2 q47_p3 q47_p4 q47_p5 q47_p6 q47_p7 q47_p8 q47_p9 q47_p10 q47_p11 q47_p12 q47_p13
1 Austria NA NA NA NA NA NA NA NA NA NA NA NA NA NA
2 Austria 2 3 8 10 10 2 4 3 1 NA NA NA NA NA
3 Austria 5 5 7 10 9 5 NA NA 0 NA NA NA NA NA
4 Austria 5 4 6 9 8 3 5 6 0 NA NA NA NA NA
5 Austria 5 NA NA NA NA NA NA NA NA NA NA NA NA NA
6 Austria NA NA NA NA NA NA NA NA NA NA NA NA NA NA
q47_p14 q47_p15
1 NA NA
2 NA NA
3 NA NA
4 NA NA
5 NA NA
6 NA NA
恐怕我对你的后续步骤了解不够,无法提供进一步帮助。
但通常为了缩放我使用 scale
函数,它以 0 为中心并归一化:
head(scale(mydata3[,-1]))