2016-05-13 2 views
2

Есть ли способ добиться следующего преобразования с помощью dplyr :: mutate_each?Dplyr Mutate_each для парных наборов столбцов

data.frame(x1 = 1:5, x2 = 6:10, y1 = rnorm(5), y2 = rnorm(5)) %>% 
    mutate(diff1 = x1 - y1, diff2 = x2 - y2) 

## x1 x2   y1   y2  diff1  diff2 
## 1 1 6 1.03645018 -0.8602099 -0.03645018 6.860210 
## 2 2 7 -1.10790835 1.6912875 3.10790835 5.308712 
## 3 3 8 0.95452119 2.7232657 2.04547881 5.276734 
## 4 4 9 0.01370762 1.6385765 3.98629238 7.361424 
## 5 5 10 0.19354354 -1.0464360 4.80645646 11.046436 

Я понимаю, что это тривиальный пример, и это легко сделать, как я описал, но я пытаюсь выполнить подобную вещь с гораздо большим набором столбцов.

Спасибо

+0

Я рад услышать другие решения, но я особенно заинтересован в том или нет, это может быть сделано с mutate_each –

+2

'melt' в длинный формат с первым «id», определяемый как исходная строка, затем группа по id и ее тривиальная. – Gregor

+0

Вы просто ищете более быстрое решение в целом? – nrussell

ответ

4

Как упоминалось в комментариях к @Gregor, если вы хотите работать с dplyr, было бы лучше получить ваши данные в аккуратном формате. Вот идея:

library(dplyr) 
library(tidyr) 

df %>% 
    add_rownames() %>% 
    gather(key, val, -rowname) %>% 
    separate(key, c("var", "num"), "(?<=[a-z]) ?(?=[0-9])") %>% 
    spread(var, val) %>% 
    mutate(diff = x - y) 

Что дает:

#Source: local data frame [10 x 5] 
# 
# rowname num  x   y  diff 
#  (chr) (chr) (dbl)  (dbl)  (dbl) 
#1  1  1  1 1.03645018 -0.03645018 
#2  1  2  6 -0.86020990 6.86020990 
#3  2  1  2 -1.10790835 3.10790835 
#4  2  2  7 1.69128750 5.30871250 
#5  3  1  3 0.95452119 2.04547881 
#6  3  2  8 2.72326570 5.27673430 
#7  4  1  4 0.01370762 3.98629238 
#8  4  2  9 1.63857650 7.36142350 
#9  5  1  5 0.19354354 4.80645646 
#10  5  2 10 -1.04643600 11.04643600 

Если по каким-то причинам вы все еще хотите, чтобы данные в широком формате после выполнения операции, вы могли бы добавить к трубе:

gather(key, value, -(rowname:num)) %>% 
    unite(key_num, key, num, sep = "") %>% 
    spread(key_num, value) 

Который дал:

#Source: local data frame [5 x 7] 
# 
# rowname  diff1  diff2 x1 x2   y1   y2 
# (chr)  (dbl)  (dbl) (dbl) (dbl)  (dbl)  (dbl) 
#1  1 -0.03645018 6.860210  1  6 1.03645018 -0.8602099 
#2  2 3.10790835 5.308713  2  7 -1.10790835 1.6912875 
#3  3 2.04547881 5.276734  3  8 0.95452119 2.7232657 
#4  4 3.98629238 7.361423  4  9 0.01370762 1.6385765 
#5  5 4.80645646 11.046436  5 10 0.19354354 -1.0464360 

данные

df <- structure(list(x1 = 1:5, x2 = 6:10, y1 = c(1.03645018, -1.10790835, 
0.95452119, 0.01370762, 0.19354354), y2 = c(-0.8602099, 1.6912875, 
2.7232657, 1.6385765, -1.046436)), .Names = c("x1", "x2", "y1", 
"y2"), class = "data.frame", row.names = c("1", "2", "3", "4", "5")) 
1

Это не использует mutate_each, и это не очень красиво, и я не думаю, что это будет очень быстро, но:

#create data set 
p<-data.frame(x1 = 1:5, x2 = 6:10, 
      y1 = rnorm(5), y2 = rnorm(5), 
      z1 = 11:15, z2 = rnorm(5), 
      w1 = rchisq(5,2), w2 = rgamma(5, .2)) 

#subset the columns by their column number and subtract them 
p[,ncol(p)+seq(1,ncol(p)/2, by = 1)]<- 
p[,seq(1,ncol(p),by = 2)]-p[,seq(2,ncol(p), by = 2)] 

data.frame р должен быть обновлен в два раза меньше столбцов, чем первоначально, новые столбцы, содержащие разницу каждой пары (1-2, 3-4, 5-6) оригиналов.

+0

Используя векторную переработку, вы можете заменить 'seq()' вызовы в вашей последней строке на 'c (T, F)' и 'c (F, T). Например, 'mtcars [, c (T, F)]' дает все нечетные столбцы, а 'mtcars [, c (F, T)]' дает все четные столбцы. – Gregor