R: объединить столбец значений в несколько новых столбцов, каждый на основе столбца индекса - PullRequest
0 голосов
/ 29 апреля 2018

Предположим, у меня есть данные:

data.frame(Plot = rep(1:2,3),Index = rep(1:3, each = 2), Val = c(1:6)*10)

  Plot Index Val
1    1     1  10
2    2     1  20
3    1     2  30
4    2     2  40
5    1     3  50
6    2     3  60

Я хочу создать новые столбцы, объединяющие / агрегирующие все Val, которые имеют общий Index для данного Plot. Я хочу сделать это для каждого Index.

  Plot Val1 Val2 Val3
1    1   10   30   50
2    2   20   40   60

Я бы хотел, чтобы все оставшиеся столбцы (например, просто Plot в этом упрощенном примере) остались в моем окончательном data.frame.

Моя попытка

Я знаю, что могу сделать это пошагово, используя aggregate() и merge(), но есть ли способ сделать это, используя один (или минимальный) вызов (ы)?

  • Любой подход великолепен, но мне всегда нравится видеть элегантный подход base R, если таковой существует ...

Обновление:

Я ищу решение, которое также хорошо работает, когда задействованы другие столбцы:

dat2 = data.frame(Plot = rep(1:2,each = 8),Year = rep(rep(2010:2011, each = 4),2), 
                  Index = rep(rep(1:2,2),4), Val = rep(c(1:4)*10,4))

   Plot Year Index Val
1     1 2010     1  10
2     1 2010     2  20
3     1 2010     1  30
4     1 2010     2  40
5     1 2011     1  10
6     1 2011     2  20
7     1 2011     1  30
8     1 2011     2  40
9     2 2010     1  10
10    2 2010     2  20
11    2 2010     1  30
12    2 2010     2  40
13    2 2011     1  10
14    2 2011     2  20
15    2 2011     1  30
16    2 2011     2  40

#Resulting in (if aggregating by sum, for example):

  Plot Year Val1 Val2 
1    1 2010   40   60 
2    1 2011   40   60 
3    2 2010   40   60 
4    2 2011   40   60 

Также, в идеале, новые столбцы должны иметь имена на основе значения Index.

  • Таким образом, если бы мой индекс был вместо A: C, мои новые столбцы были бы ValA, ValB и ValC

Ответы [ 2 ]

0 голосов
/ 30 апреля 2018

Кажется, вам нужно решение base R: тогда вы можете сделать что-то вроде:

m = aggregate(Val~.,dat2,sum)
reshape(m,v.names = "Val",idvar = c("Plot","Year"),timevar = "Index",direction = "wide")
  Plot Year Val.1 Val.2
1    1 2010    40    60
2    2 2010    40    60
3    1 2011    40    60
4    2 2011    40    60

Но вы можете использовать другие функции:

do.call(data.frame,aggregate(Val~Plot+Year,m,I))
  Plot Year Val.1 Val.2
1    1 2010    40    60
2    2 2010    40    60
3    1 2011    40    60
4    2 2011    40    60

Или используя библиотеку reshape2, вы можете решить проблему следующим образом:

library(reshape2)
dcast(dat2,Plot+Year~Index,sum,value.var = "Val")
  Plot Year  1  2
1    1 2010 40 60
2    1 2011 40 60
3    2 2010 40 60
4    2 2011 40 60
0 голосов
/ 29 апреля 2018

Можно подумать об использовании функций gather, unite и spread для получения желаемого результата, как указано в OP.

library(tidyverse)
df <- data.frame(Plot = rep(1:2,3),Index = rep(1:3, each = 2), Val = c(1:6)*10)


df %>% gather(key, value, -Plot, -Index) %>%
  unite("key", c(key,Index), sep="") %>%
  spread(key, value)

#   Plot Val1 Val2 Val3
# 1    1   10   30   50
# 2    2   20   40   60

Примечание: Существуют и другие короткие варианты (как правильно указано @Onyambu), но, опять же, в соответствии с именами столбцов желаний ОП необходимо изменить.

spread(df, Index, Val)
#   Plot  1  2  3
# 1    1 10 30 50
# 2    2 20 40 60

aggregate(Val~Plot,df,I)
#   Plot Val.1 Val.2 Val.3
# 1    1    10    30    50
# 2    2    20    40    60

Обновлено: На основе 2-го кадра данных из OP.

dat2 = data.frame(Plot = rep(1:2,each = 8),Year = rep(rep(2010:2011, each = 4),2), 
                  Index = rep(rep(1:2,2),4), Val = rep(c(1:4)*10,4))


library(tidyverse)
library(reshape2)

dat2 %>% gather(key, value, -Plot, -Index, -Year) %>%
  unite("key", c(key,Index), sep="") %>%
  dcast(Plot+Year~key, value.var = "value")

#   Plot Year Val1 Val2
# 1    1 2010    2    2
# 2    1 2011    2    2
# 3    2 2010    2    2
# 4    2 2011    2    2
...