Как я могу изменить свои данные, переместив строки в новые столбцы? - PullRequest
1 голос
/ 13 марта 2020

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

У меня есть такие данные:

Input = (
 'col1 col2
  A 2
  B 4
  A 7
  B 3
  A 4
  B 2
  A 4
  B 6
  A 3
  B 3')
df = read.table(textConnection(Input), header = T)

> df
   col1 col2
1     A    2
2     B    4
3     A    7
4     B    3
5     A    4
6     B    2
7     A    4
8     B    6
9     A    3
10    B    3

И я хотел бы иметь что-то вроде этого, где имена столбцов не важны:

      col1 v1   v2   v3   v4   v5
1     A    2    7    4    4    3
2     B    4    3    2    6    3

Пока что я сделал что-то вроде:

res_1 <- aggregate(col2 ~., df, toString)
  col1          col2
1    A 2, 7, 4, 4, 3
2    B 4, 3, 2, 6, 3

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

res_2 <- do.call("rbind", strsplit(res_1$col2, ","))
     [,1] [,2] [,3] [,4] [,5]
[1,] "2"  " 7" " 4" " 4" " 3"
[2,] "4"  " 3" " 2" " 6" " 3"

Адн, наконец, объединить его и удалить ненужные столбцы:

final <- cbind(res_1,res_2)
final$col2 <- NULL
  col1 1  2  3  4  5
1    A 2  7  4  4  3
2    B 4  3  2  6  3

Итак, у меня есть желаемый результат, но я не удовлетворен методом, я уверен, что есть одна простая и короткая команда для этого. Как я уже сказал, я хотел бы изучить новые более элегантные варианты, используя различные пакеты. Спасибо!

Ответы [ 2 ]

1 голос
/ 13 марта 2020

Вопрос помечен с помощью reshape2 и reshape, поэтому мы покажем, как использовать этот пакет и базовую функцию reshape. Также показано использование dplyr / tidyr. Наконец, мы показываем решение data.table и второе базовое решение R, используя xtabs.

reshape2 Добавьте столбец группы и затем преобразуйте из длинной в широкую форму:

library(reshape2)

df2 <- transform(df, group = paste0("v", ave(1:nrow(df), col1, FUN = seq_along)))
dcast(df2, col1 ~ group, value.var = "col2")

, дающий:

  col1 v1 v2 v3 v4 v5
1    A  2  7  4  4  3
2    B  4  3  2  6  3

2) изменить форму Используя df2 из (1), мы имеем следующее базовое решение R с использованием функции reshape:

wide <- reshape(df2, dir = "wide", idvar = "col1", timevar = "group")
names(wide) <- sub(".*\\.", "", names(wide))
wide

подача:

  col1 v1 v2 v3 v4 v5
1    A  2  7  4  4  3
2    B  4  3  2  6  3

3) dplyr / tidyr

library(dplyr)
library(tidyr)

df %>%
  group_by(col1) %>%
  mutate(group = paste0("v", row_number())) %>%
  ungroup %>%
  pivot_wider(names_from = "group", values_from = "col2")

подача:

# A tibble: 2 x 6
  col1     v1    v2    v3    v4    v5
  <fct> <int> <int> <int> <int> <int>
1 A         2     7     4     4     3
2 B         4     3     2     6     3

4) data.table

library(data.table)

as.data.table(df)[, as.list(col2), by = col1]

, дающий:

   col1 V1 V2 V3 V4 V5
1:    A  2  7  4  4  3
2:    B  4  3  2  6  3

5) xtabs Другое базовое решение R использует df2 из (1) и xtabs. Это создает объект класса c ("xtabs", "table") `. Обратите внимание, что он маркирует размеры.

xtabs(col2 ~., df2)

, давая:

    group
col1 v1 v2 v3 v4 v5
   A  2  7  4  4  3
   B  4  3  2  6  3
1 голос
/ 13 марта 2020

Вы можете просто сделать,

do.call(rbind, split(df$col2, df$col1))
#  [,1] [,2] [,3] [,4] [,5]
#A    2    7    4    4    3
#B    4    3    2    6    3

Вы можете обернуть его в data.frame() для преобразования из матрицы в df

...