Преобразование data.frame в многомерную матрицу - PullRequest
4 голосов
/ 22 апреля 2019

Например, рассмотрим следующие данные

> sample.df
  f1 f2   x1   x2   x3
1  2  2 7.28 9.40 5.02
2  1  1 6.30 9.56 3.74
3  2  1 6.88 8.72 3.14
4  1  2 6.68 9.58 3.84

Интересно, как написать MAGIC, чтобы

> sample.matrix <- MAGIC(sample.df)
> sample.matrix[1, 1, ]
[1] 6.30 9.56 3.74
> sample.matrix[1, 2, ]
[1] 6.68 9.58 3.84

Как правило, sample.matrix[x, y, ] выбирает строку во фрейме данных с помощью sample.df[sample.df$f1 == x & sample.df$f2 == y, ], а затем удаляет лишние столбцы, указывающие значения f1 и f2. Обратите внимание, что каждая комбинация (f1, f2) появляется и появляется только один раз в кадре данных.

Моей первой мыслью было as.matrix, за которым следовал dim<-, но строки во фрейме данных не сортируются. Сортировка потребует O (n * log (n)), но я просто хочу создать таблицу, поэтому теоретически сложность времени может быть связана с O (n).

Было бы лучше, если бы вы могли использовать векторизацию, если это возможно.

Ответы [ 2 ]

3 голосов
/ 22 апреля 2019

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

Предполагая, что df ваш sample.df,

m1 <- matrix(do.call(paste, df[with(df, order(f1, f2)),-c(1, 2)]), nrow = 2, byrow = TRUE)
m1[1, 2]
#[1] "6.68 9.58 3.84"
m1[1, 1]
#[1] "6.3 9.56 3.74"
m1[2, 1]
#[1] "6.88 8.72 3.14"
m1[2, 2]
#[1] "7.28 9.4 5.02"

Вы можете получить их как числовые векторы, разделив, т.е.

as.numeric(strsplit(m1[1, 2], ' ')[[1]])
#[1] 6.68 9.58 3.84
1 голос
/ 22 апреля 2019

РЕДАКТИРОВАТЬ

После повторного чтения вопроса, я думаю, мы можем использовать split без order ing, чтобы избежать этапа сортировки.Поскольку f1 и f2 уникальны для каждой строки, мы можем сделать

split(sample.df[, -(1:2)], list(sample.df$f1, sample.df$f2))


#$`1.1`
#   x1   x2   x3
#2 6.3 9.56 3.74

#$`2.1`
#    x1   x2   x3
#3 6.88 8.72 3.14

#$`1.2`
#    x1   x2   x3
#4 6.68 9.58 3.84

#$`2.2`
#    x1  x2   x3
#1 7.28 9.4 5.02

Оригинальный ответ

Я не совсем уверен вцель, но одним из способов является order sample.df на f1, f2, а затем подмножество с использованием Map

new_df <- sample.df[with(sample.df, order(f1, f2)),]

Map(function(x, y) new_df[with(new_df, f1 == x & f2 == y), -(1:2)],
                   new_df$f1, new_df$f2)

#[[1]]
#   x1   x2   x3
#2 6.3 9.56 3.74

#[[2]]
#    x1   x2   x3
#4 6.68 9.58 3.84

#[[3]]
#    x1   x2   x3
#3 6.88 8.72 3.14

#[[4]]
#    x1  x2   x3
#1 7.28 9.4 5.02

Если вышеуказанное значение является ожидаемым, то каждая строка в new_df это выход, который вы хотите.Если вы хотите, чтобы они были в виде отдельного списка, мы также можем split каждую строку

split(new_df[, -(1:2)], seq_len(nrow(new_df)))

, что даст вам тот же результат.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...