2016-07-27 52 views
0

哪些應用函數應該用來避免下面代碼中的for循環?變量標籤現在是簡單的佔位符 - 目標是使用此過程在R中設置密碼本,以便輕鬆導出到在SPSS中打開時密碼簿準備就緒的SPSS。理想情況下,這將簡化我在R中爲自己的工作而工作的能力,但與使用SPSS的同事兼容。想避免在r循環中使用其中一個應用函數

data1 <- read.table(header = TRUE, sep=",", 
        text = " 
SubjectID,Age,WeightPRE,WeightPOST,Height,SES,GenderSTR,GenderCoded 
1,45,150,145,5.6,2,m,1 
2,50,167,166,5.4,2,f,2 
3,35,143,135,5.6,2,F,2 
4,44,216,201,5.6,2,m,1 
5,32,243,223,6,2,m,1 
6,48,165,145,5.2,2,f,2 
7,50,132,132,5.3,2,m,1 
8,51,110,108,5.1,3,f,2 
9,46,167,158,5.5,2,, 
10,35,190,200,5.8,1,Male,1 
11,36,230,210,6.2,1,m,1 
12,40,200,195,6.1,1,f,2 
13,45,180,185,5.9,3,f,2 
14,52,240,220,6.5,2,m,1 
15,24,250,240,6.4,2,M,1 
16,35,175,174,5.8,2,F,2 
17,51,220,221,6.3,2,m,1 
18,43,230,215,2.6,2,m,1 
19,36,190,180,5.7,1,female,2 
20,44,260,240,6.4,3,male,1 
") 

var.labels = c(SubjectID="aaa", 
       Age="Age in Years", 
       WeightPRE="bbb", 
       WeightPOST="ccc", 
       Height="ddd", 
       SES="eee", 
       GenderSTR="fff", 
       GenderCoded="ggg") 

for(i in 1:8){ 
    attr(dtab1[[names(var.labels)[i]]],"label") <- var.labels[names(var.labels)[i]] 
} 

# using the haven package 
# this creates SPSS datafile with variable labels 
library(haven) 
write_sav(dtab1,"out1.sav") 
+0

在這種情況下的for循環是完全可以接受的,但是您應該將可迭代值從'1:8'更改爲'1:length(var.labels)'以保持通用。是否有你不想使用for循環的原因。 – vincentmajor

回答

0

在這種情況下,for循環可能是在此材質中添加的最佳方法。作爲一個例子,這裏大致是「最好」的方式來使用lapply這種材料添加:

data1[] <- lapply(1:8, function(i) { 
           # assign the label 
           attr(data1[[names(var.labels)[i]]], "label") <- 
            var.labels[names(var.labels)[i]] 
           # return the vector 
           data1[[names(var.labels)[i]]] 
      }) 

我的眼睛,這是不容易閱讀,包括一些不必要相對於你的for循環拉伸。

+0

謝謝'lmo' –

3

感謝您的lmo您的建議。

大多數情況下,我想盡可能避免出現循環 - 但我認爲在這種情況下,for循環可以正常使用。我只是跑使用microbenchmark包裝系統時間分析,得到了以下...

library(microbenchmark) 
microbenchmark(
    data1[] <- lapply(1:8, function(i) { 
    # assign the label 
    attr(data1[[names(var.labels)[i]]], "label") <- 
     var.labels[names(var.labels)[i]] 
    # return the vector 
    data1[[names(var.labels)[i]]] 
    }) 
) 

這就造成:

Unit: microseconds expr data1[] <- lapply(1:8, function(i) { attr(data1[[names(var.labels)[i]]], "label") <- var.labels[names(var.labels)[i]] data1[[names(var.labels)[i]]] }) min lq mean median uq max neval 380.291 412.986 638.6603 445.2185 661.102 2863.767 100

和for循環跑得更快......

microbenchmark(
    for(i in 1:8){ 
    attr(data1[[names(var.labels)[i]]],"label") <- var.labels[names(var.labels)[i]] 
    } 
) 

這給了這次分析:

Unit: microseconds expr for (i in 1:8) { attr(data1[[names(var.labels)[i]]], "label") <- var.labels[names(var.labels)[i]] } min lq mean median uq max neval 179.015 197.798 289.9299 209.624 278.7255 1186.783 100

謝謝您對我的問題的反饋和考慮。

0

至於循環算是不錯的選擇,這裏的一環本身是一個很小的改善:

for(var in names(var.labels)) { 
    attr(data1[[var]], "label") <- var.labels[var] 
} 

改進包括:

  • 推廣到需要
  • 將不會運行儘可能多的標籤如果你忽略爲任何變量創建標籤
  • 更短的代碼和更容易閱讀(至少對我來說)
+0

謝謝西蒙這個更清潔和更通用的代碼! –