2015-01-17 128 views
2

我想我寫的是「沒有問題太容易」的精神,我只是一個普通的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對象TTT,其中包含兩組不同的變量,以便稍後在模擬中使用。這個任務必須在構成「主」列表「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)從更一般的立場來看,這種處理方式是正確的嗎?分割,定義特定於任務的功能,用lapply()調用它們,最後重新組合?

謝謝您的任何建議或意見。 Andrea

+0

如果我處在你的位置,我會先轉換歐洲選舉研究數據成整齊的格式,然後再處理來港,然後正常化。除非你使用4GB內存的筆記本電腦運行它,或者有一些理由超出了計算限制,否則我認爲你不需要分割數據。 –

+1

告訴你用來導入數據的功能,NA是如何編碼的,它會爲你處理。 – Roland

+1

關於'recode',而不是重複'val < - c(77,88,89,98,99,999); lapply(processed.dat,function(x){x [] <-lapply(x,function(.x){.x [.x%in%val] < - NA; .x}); x})' – akrun

回答

2

這應該用於數據清理。我使用庫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])) 
+0

謝謝@ Serban-tanasa,它的工作原理和簡化很多,我需要進行分割,因爲我必須分別進行國別分析,因此,一種選擇是以27個國家分開的代碼塊,每個df一個,在Stata中,我將使用相應的27個數據集運行'for'循環。在R上,對於我一直在閱讀的內容,似乎在ladfly()它可以更高效地工作 – 000andy8484

+0

@ R.newby在完成清潔之後,您可以隨時拆分*除非正常化是按照國家來進行的,你也可以在分裂之前做到這一點。 PS:for循環沒有錯。代碼的要點是a)讓它工作b)讓你明白它的作用,只有遠處的c)才能高效。 –

+0

@ R.newby Google「split-apply-combine」。你通常不需要使用'split'和'lapply',因爲它們更方便,效率更高(參見軟件包dplyr或data.table)。 – Roland