Как я могу растопить столбцы, удерживая две вместе?

У меня есть данные этого широкого формата, которые я хочу преобразовать в длинный формат

    Cond    Construct   Line    Plant   Tube_shoot  weight_shoot    Tube_root   weight_root
1   Standard            NA      NA      2           199.95          -           -
2   Cd0     IIF         43.1    1       3           51.87           4           10.39
3   Cd0     IIF         43.1    2       5           81.80           6           15.05
4   Cd0     IIF         43.1    3       7           101.56          8           16.70

В основном я хочу, чтобы Tube_shoot и weight_shoot были вместе, то есть рассматривать эти два столбца как один для плавления. Но потому что я могу использовать только

id.vars=c("Cond","Construct","Line","Plant")

результат не совсем то, что я хочу.

У меня есть два (уродливых) решения:

  1. Я плавлю дважды, сначала по measure.vars = c ("Tube_shoot", "Tube_root"), затем по весу, а затем удаляю половину строк, где результат просто неверный. Для меня это невозможно, потому что у меня разная длина данных, и мне всегда приходилось проверять, беру ли я правильные строки.

  2. Вставляю «тюбик» с «грузиком» в новый столбик, вынимаю остальные, плавлю, а потом снова разбираю.

  3. Скопируйте их по одному в excel. Но с сотнями строк я бы лучше научился делать это в R.

Я уверен, что есть способ получше.

Что хочу в итоге:

    Cond    Construct   Line    Plant   Tube        weight
1   Standard            NA      NA      2           199.95
2   Cd0     IIF         43.1    1       3           51.87
3   Cd0     IIF         43.1    2       5           81.80
4   Cd0     IIF         43.1    3       7           101.56
2   Cd0     IIF         43.1    1       4           10.39
3   Cd0     IIF         43.1    2       6           15.05
4   Cd0     IIF         43.1    3       8           16.70

person riselin    schedule 25.11.2014    source источник


Ответы (3)


Вы могли бы попробовать

 res <- reshape(df1, idvar=c('Cond', 'Construct', 'Line', 'Plant'),
              varying=5:8, direction='long', sep="_")

 res1 <-  res[res$weight!='-', -5]
 row.names(res1) <- NULL

 res1
 #      Cond Construct Line Plant Tube weight_shoot
 #1 Standard             NA    NA    2       199.95
 #2      Cd0       IIF 43.1     1    3        51.87
 #3      Cd0       IIF 43.1     2    5         81.8
 #4      Cd0       IIF 43.1     3    7       101.56
 #5      Cd0       IIF 43.1     1    4        10.39
 #6      Cd0       IIF 43.1     2    6        15.05
 #7      Cd0       IIF 43.1     3    8        16.70

данные

 df1 <- structure(list(Cond = c("Standard", "Cd0", "Cd0", "Cd0"), 
  Construct = c("", "IIF", "IIF", "IIF"), Line = c(NA, 43.1, 43.1, 43.1),
  Plant = c(NA, 1L, 2L, 3L), Tube_shoot = c(2L, 3L, 5L, 7L), weight_shoot = 
  c(199.95,51.87, 81.8, 101.56), Tube_root = c("-", "4", "6", "8"), 
  weight_root = c("-", "10.39", "15.05", "16.70")), .Names = c("Cond",
  "Construct", "Line", "Plant", "Tube_shoot", "weight_shoot", "Tube_root",
  "weight_root"), class = "data.frame", row.names = c("1", "2", "3", "4"))
person akrun    schedule 25.11.2014
comment
Спасибо, это абсолютно идеально. Я не пробовал изменять форму, поскольку переходил по этой ссылке: cookbook-r.com/Manipulating_data/ < / а> - person riselin; 25.11.2014
comment
@akrun, dcast.data.table сможет работать с такими данными с версии 1.9.8 и далее. - person A5C1D2H2I1M1N2O1R2T1; 25.11.2014

Другой вариант, используя dplyr и tidyr:

library(dplyr)
libarary(tidyr)

gather(df1, x, Tube, c(Tube_shoot, Tube_root)) %>% 
   mutate(weight = ifelse(grepl("*root$", x), weight_root, weight_shoot)) %>%
   select(-c(weight_shoot, weight_root, x))

#      Cond Construct Line Plant Tube weight
#1 Standard             NA    NA    2 199.95
#2      Cd0       IIF 43.1     1    3  51.87
#3      Cd0       IIF 43.1     2    5   81.8
#4      Cd0       IIF 43.1     3    7 101.56
#5 Standard             NA    NA    -      -
#6      Cd0       IIF 43.1     1    4  10.39
#7      Cd0       IIF 43.1     2    6  15.05
#8      Cd0       IIF 43.1     3    8  16.70
person talat    schedule 25.11.2014

Вы можете рассмотреть merged.stack из моего пакета "splitstackshape", с помощью которого вы можете сделать что-то вроде:

library(splitstackshape)
merged.stack(as.data.table(df1, keep.rownames = TRUE), 
             var.stubs = c("Tube", "weight"), sep = "_")
#    rn     Cond Construct Line Plant .time_1 Tube weight
# 1:  1 Standard             NA    NA    root    -      -
# 2:  1 Standard             NA    NA   shoot    2 199.95
# 3:  2      Cd0       IIF 43.1     1    root    4  10.39
# 4:  2      Cd0       IIF 43.1     1   shoot    3  51.87
# 5:  3      Cd0       IIF 43.1     2    root    6  15.05
# 6:  3      Cd0       IIF 43.1     2   shoot    5   81.8
# 7:  4      Cd0       IIF 43.1     3    root    8  16.70
# 8:  4      Cd0       IIF 43.1     3   shoot    7 101.56

Конечно, вы также можете добавить [Tube != "-" | weight != "-"] в конец, чтобы удалить строки, в которых "Tube" или "weight" имеют "-" ... но учтите, что это не преобразует эти столбцы в числовые значения волшебным образом :-)

person A5C1D2H2I1M1N2O1R2T1    schedule 25.11.2014
comment
Интересно, было бы проще, если бы merged.stack по умолчанию конвертировал фреймы данных в data.table, если только он не может работать и с фреймами данных? - person David Arenburg; 25.11.2014
comment
@DavidArenburg, он автоматически конвертируется в data.tables. Я сделал as.data.table, потому что мне нужны были названия для заказа, если они потребуются позже. - person A5C1D2H2I1M1N2O1R2T1; 25.11.2014
comment
Ну ладно, хорошее решение - person David Arenburg; 25.11.2014
comment
Это решение не работает для меня с моими исходными данными, и даже с df1, предоставленным akrun, это не так. Для этого мне пришлось добавить id.vars = c ('Cond', 'Construct', 'Line', 'Plant'). - person riselin; 25.11.2014
comment
@riselin, какую версию splitstackshape вы используете? В версии 1.4 и выше он пытается угадать id.vars. - person A5C1D2H2I1M1N2O1R2T1; 25.11.2014
comment
только что проверил, это версия 1.2 (отредактируйте: я использую R studio на Mac, и это то, что я загрузил с помощью install.packages (splitstackshape) полчаса назад. Кроме того, кнопка автоматического обновления утверждает, что все обновлены) - person riselin; 25.11.2014
comment
@riselin, возможно, вам придется установить его из исходников. У меня нет Mac, поэтому я не могу подтвердить. - person A5C1D2H2I1M1N2O1R2T1; 25.11.2014