Сформируйте кадр данных, добавив ноль в R - PullRequest
0 голосов
/ 05 октября 2018

У меня есть фрейм данных с расстоянием в первом столбце и классом во втором:

data.tab <- read.table(text = "
644 1
76  1
78  1
350 1 
45  1
37  2
366 2 
46  2
71  3
28  3 
97  3
30  3
55  3 
65  3
116 3  
30  3
18  4
143 4
99  4")

Я хочу преобразовать его в новый фрейм данных, добавив ноль в соответствии с самым длинным классом.Результат будет:

data.tab <- read.table(text = "
1 644 76  78 350 45 0  0  0
2 37  366 46  0  0  0  0  0
3 71  28  97 30 55 65 116 30 
4 18  143 99  0  0  0  0  0")

Ответы [ 4 ]

0 голосов
/ 05 октября 2018

Использование df в качестве имени вместо data.tab:

MAX <- max(table(df$V2))
t(sapply(split(df$V1, df$V2), function(x) c(x, rep(0, MAX-length(x)))))

(Идея состоит в том, чтобы разбить V1 на группы, определенные V2, чтобы векторы были равны по длине, добавив 0 'sв конце, когда это необходимо, и затем объединяет это в одну матрицу. sapply делает последний бит автоматически, но по столбцам, поэтому необходимо t.)

другим способом, используя length<-

U <- unstack(df) # a hack learned from G.Grothendieck's answer
U <- with(df, split(V1,V2)) # more readable version of the above
M <- max(lengths(U))
R <- t(sapply(U, "length<-", M)) # setting all lengths equal 
replace(R, is.na(R), 0)  # replacing NAs by zeroes

И (довольно нечитаемый) однострочный, делающий то же самое:

"[<-"(R<-t(sapply(U<-unstack(df),"length<-",max(lengths(U)))),is.na(R),0)
0 голосов
/ 05 октября 2018

1) xtabs Используя только базу R, создайте столбец порядкового номера в классе, а затем используйте xtabs, чтобы преобразовать его в таблицу.Наконец преобразовать это в фрейм данных.Пропустите последнюю строку кода, если таблицы достаточно.

data.tab2 <- transform(data.tab, seq = ave(V2, V2, FUN = seq_along))
xt <- xtabs(V1 ~ V2 + seq, data.tab2)
as.data.frame.matrix(xt)

, давая:

    1   2  3   4  5  6   7  8
1 644  76 78 350 45  0   0  0
2  37 366 46   0  0  0   0  0
3  71  28 97  30 55 65 116 30
4  18 143 99   0  0  0   0  0

2) ts Другое базовое решение R состоит в преобразовании элементовкаждого класса в ряд ts, дающий tt многомерный временной ряд с NA на концах более коротких.Преобразуйте эти NA в 0 во второй строке кода, а затем преобразуйте их во фрейм данных в последней строке.

tt <- do.call("cbind", lapply(unstack(data.tab), ts))
tt[] <- ifelse(is.na(tt), 0, tt)
as.data.frame(t(tt))

3) Используя data.tab2 из (1), используйтеtapply, чтобы создать матрицу mat и затем преобразовать ее в data.frame.Пропустите последнюю строку кода, если матрицы достаточно.

mat <- with(data.tab2, tapply(V1, list(V2, seq), c, default = 0))
as.data.frame(mat)

Примечание

Комментарий утверждал, что ifelse будет медленнее, чем предлагаемая альтернатива, но сравнительный анализ не показал общей разницы вданные в вопросе.Конечно, производительность может быть не очень важной здесь, в первую очередь.

library(rbenchmark)

benchmark(
  ifelse = {
    tt <- do.call("cbind", lapply(unstack(data.tab), ts))
    tt[] <- ifelse(is.na(tt), 0, tt)
    as.data.frame(t(tt))
  },
  replace = {
    tt <- do.call("cbind", lapply(unstack(data.tab), ts))
    tt[is.na(tt)] <- 0
    as.data.frame(t(tt))
  }
)[1:4]

давая:

     test replications elapsed relative
1  ifelse          100    0.25        1
2 replace          100    0.25        1
0 голосов
/ 05 октября 2018

с использованием data.table транспонирования

cbind(sort(unique(data.tab$V2)),do.call(rbind,transpose(transpose(split(data.tab$V1, data.tab$V2), 0))))

#     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
#[1,]    1  644   76   78  350   45    0    0    0
#[2,]    2   37  366   46    0    0    0    0    0
#[3,]    3   71   28   97   30   55   65  116   30
#[4,]    4   18  143   99    0    0    0    0    0
0 голосов
/ 05 октября 2018

Это, по сути, сводится к простой длинной или широкой форме

library(tidyverse)
data.tab %>%
    group_by(V2) %>%
    mutate(col = paste0("V", 1:n())) %>%
    spread(col, V1, fill = 0) %>%
    ungroup()
## A tibble: 4 x 8
#     V1    V2    V3    V4    V5    V6    V7    V8
#  <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#1   644    76    78   350    45     0     0     0
#2    37   366    46     0     0     0     0     0
#3    71    28    97    30    55    65   116    30
#4    18   143    99     0     0     0     0     0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...