R из длинного в широкий фрейм данных с вещественными столбцами

#r #dataframe #tidyverse #reshape #tibble

#r #фрейм данных #tidyverse #изменить форму #tibble

Вопрос:

У меня есть небольшой вопрос, связанный с изменением формы моего фрейма данных, где у меня есть данные ID «grouped_by». У меня есть следующая схема df ( 2 примерных экземпляра, которые я хочу расширить (всего у меня > 5000)):

    id                  solver   scoreA  scoreB  group   size 
   <chr>               <chr>    <dbl>   <dbl>   <chr>   <dbl>
 1 instance_1          s1       1        0.5    g1      1000                     
 2 instance_1          s2       100      50     g1      1000
  

… что я хочу получить, так это:

    id           solver.best  scoreA.s1  scoreA.s2  scoreB.s1   scoreB.s2  group   size 
   <chr>        <chr>        <dbl>      <dbl>      <dbl>       <dbl>      <chr>   <dbl>
 1 instance_1   s1           1          100        0.5         50         g1      1000                     
  

Ценю вашу помощь.
BR

Комментарии:

1. Если у вас более 5000 строк, и вы хотите сделать это — у вас будет около 5000 столбцов, это почти наверняка неправильный путь. То, чего вы пытаетесь достичь, должно иметь альтернативный маршрут.

2. идентификатор всегда группирует 2 экземпляра … в основном говоря, что я хочу, чтобы две строки стали плоскими. т. Е. увеличились с 5000 строк до 2500

3. Вы можете посчитать, в чем разница между 5 x 5000 и 2500 x 5000?

4. Я не понимаю вашу точку зрения. Я признаю, что распространение с помощью методов tidyverse может не привести к желаемому результату, и без группировки он будет иметь размер 2500 x 5000 df. Кроме этого, я не вижу никакой фатальности в идее сжать 2 строки в одну, сгруппированную по идентификатору…

5. Цель просьбы вас поделиться dput заключается в том, что мы можем скопировать ваши данные (или их часть) в нашу среду R и использовать их. Когда вы обновляете свой пост неполным dput (который мы не можем скопировать), это все равно что вообще не делиться. Если ваши данные очень большие, вы можете использовать только первые несколько строк, например dput(head(df)) , для первых 6 строк.

Ответ №1:

Возможно, вы можете попробовать приведенный ниже код

 reshape(within(df, Q <- ave(seq(nrow(df)), id, FUN = seq_along)),
  direction = "wide",
  idvar = "id", 
  timevar = "Q"
)
  

что дает

 > reshape(cbind(df,Q = seq(nrow(df))),direction = "wide",idvar = "id",timevar = "Q")
          id solver.1 scoreA.1 scoreB.1 group.1 size.1 solver.2 scoreA.2
1 instance 1       s1        1      0.5      g1   1000       s2      100
  scoreB.2 group.2 size.2
1       50      g1   1000
  

Данные

 > dput(df)
structure(list(id = c("instance 1", "instance 1"), solver = c("s1", 
"s2"), scoreA = c(1L, 100L), scoreB = c(0.5, 50), group = c("g1",
"g1"), size = c(1000L, 1000L)), class = "data.frame", row.names = c("1",
"2"))
  

Комментарии:

1. спасибо, но для меня это возвращает только значения NA :/…. У меня больше, чем всего на 2 строки. Но всегда есть 2 экземпляра с идентификатором groubed_by…

2. @gero Вы использовали данные в моем ответе? В противном случае, пожалуйста, dput() ваши данные, тогда я посмотрю, что произошло

3. структура (список(идентификатор = c («экземпляр 1», «экземпляр 1», «экземпляр 2», «экземпляр 2», [… другие экземпляры / группы …], решатель = c («S1», «S2», [… больше решателя …], scoreA = c(3.3818, 358.1937, …., scoreB = c(1.3818, 100.1937, …., group = c(«g1», «g1», …., size = c(«1000», «1000», ….)

4. @gero Не могли бы вы поместить свои данные в свой пост? Похоже, данные, которые вы указали в комментарии, не являются полными

5. Данные конфиденциальны. Однако, вот все из dput() (найти в отредактированном сообщении)

Ответ №2:

Поскольку я все еще хочу иметь удобный, например, tidyverse, передовой опыт, я все еще хочу поделиться практическим подходом, который концептуально работает так же хорошо :):

 # create empty (wide) target df
wide_df <- data.frame(matrix(ncol = 8, nrow = 0))

names <- c("id", "best_solver", "scoreA_s1", "scoreA_s2",
           "scoreB_s1", "scoreB_s2", "group", "size")
colnames(wide_df) <- names


# traverse grouped by and arranged original (long) df 
for(i in seq(2, length(long_df$group), by = 2)){
  wide_df[i/2, "id"] <- long_df[i, "id"]
  wide_df[i/2, "best_solver"] <- long_df[which(long_df[(i-1):i, "scoreA"] ==
                                 min(long_df[i-1, "scoreA"], long_df[i, "scoreA"])), 
                                 "solver"]
  wide_df[i/2, "scoreA_s1"] <- long_df[i-1, "scoreA"]
  wide_df[i/2, "scoreA_s2"] <- long_df[i, "scoreA"]
  wide_df[i/2, "scoreB_s1"] <- long_df[i-1, "scoreB"]
  wide_df[i/2, "scoreB_s2"] <- long_df[i, "scoreB"]
  wide_df[i/2, "group"] <- long_df[i, "group"]
  wide_df[i/2, "size"] <- long_df[i, "size"]
}