使用R中的ddply缩放数据框中的多个列

时间:2016-07-28 19:00:23

标签: r plyr

我的数据框看起来像

ID         Lot    SubLot  test1   test2   test3
dffk        A       A1      6       10      10
wdwd        A       A1      8       6       5
ewew        A       A2      2       9       3
llde        A       A2      2       10      6
e3rw        B       B1      8       2       2
qweo        B       B2      2       9       8
cmve        B       B2      6       5       9
owdf        B       B2      10      3       2

我的目标是更换" 测试"具有标准化值的列。必须在按批次 SubLot 列进行分组时进行标准化。
我考虑过使用 plyr pckage中的 ddply 。我可以使用以下方法为单个列执行此操作:

new_data <- ddply(old_data, c("Lot","SubLot"), transform, test1 = scale(test1))

如果我想为所有人执行此操作,语法应如何&#34; 测试&#34;列一次?

非常感谢, 大卫

2 个答案:

答案 0 :(得分:0)

如果您愿意使用dplyr,请查看mutate_at

library(dplyr)

scale1 <- function(x) scale(x)[,1]

old_data %>% group_by(Lot, SubLot) %>% 
    mutate_at(vars(contains("test")), scale1)

#Source: local data frame [8 x 6]
#Groups: Lot, SubLot [4]

#      ID    Lot SubLot      test1      test2      test3
#  <fctr> <fctr> <fctr>      <dbl>      <dbl>      <dbl>
#1   dffk      A     A1 -0.7071068  0.7071068  0.7071068
#2   wdwd      A     A1  0.7071068 -0.7071068 -0.7071068
#3   ewew      A     A2        NaN -0.7071068 -0.7071068
#4   llde      A     A2        NaN  0.7071068  0.7071068
#5   e3rw      B     B1        NaN        NaN        NaN
#6   qweo      B     B2 -1.0000000  1.0910895  0.4402255
#7   cmve      B     B2  0.0000000 -0.2182179  0.7043607
#8   owdf      B     B2  1.0000000 -0.8728716 -1.1445862

开始的列名称与测试

一词匹配
old_data %>% group_by(Lot, SubLot) %>% 
    mutate_at(vars(matches("^test")), scale1)

由于您提到您有数千个列,因此使用data.table会更有效:

cols <- grep("test", names(old_data), value = T)
old_data[,cols] <- lapply(old_data[,cols], as.double)

library(data.table)
setDT(old_data)[, (cols) := lapply(.SD, scale1) , by = .(Lot, SubLot), .SDcols = cols] 

答案 1 :(得分:0)

@Sumedh,再次感谢您的帮助。不幸的是,您的最新代码也无效。我厌倦了规模并通过定义定义它的自定义函数解决了这个问题:

my.scale = function(x,na.rm=TRUE) (x-mean(x,na.rm=TRUE))/sd(x,na.rm=TRUE)

old_data <- old_data %>% group_by(Lot) %>% 
  mutate_each( funs(my.scale), contains("test"))