Самое быстрое вращение по всей ширине в R - PullRequest
12 голосов
/ 15 марта 2011

Я имею дело с простой таблицей вида

date         variable   value
1970-01-01   V1         0.434
1970-01-01   V2         12.12
1970-01-01   V3         921.1
1970-01-02   V1         -1.10
1970-01-03   V3         0.000
1970-01-03   V5         312e6
...          ...        ...

Пары (дата, переменная) являются уникальными. Я хотел бы преобразовать эту таблицу в широкоформатную.

date         V1         V2         V3         V4         V5        
1970-01-01   0.434      12.12      921.1      NA         NA
1970-01-02   -1.10      NA         NA         NA         NA
1970-01-03   0.000      NA         NA         NA         312e6

И я хотел бы сделать это как можно быстрее, поскольку мне приходится многократно повторять операцию над таблицами с записями 1e6. В родном режиме R я считаю, что и tapply(), reshape() и d*ply() преобладают по скорости data.table. Я хотел бы проверить производительность последнего с помощью решения на основе sqlite (или другой БД). Это было сделано раньше? Есть ли прирост производительности? И как можно преобразовать значение high-to-wide в sqlite, когда число «широких» полей (дата) является переменным и не известно заранее?

Ответы [ 2 ]

4 голосов
/ 15 марта 2011

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

Времена использования tall из сообщения Прасада:

pivot = function(col, row, value) {
  col = as.factor(col)
  row = as.factor(row)
  mat = array(dim = c(nlevels(row), nlevels(col)), dimnames = list(levels(row), levels(col)))
  mat[(as.integer(col) - 1L) * nlevels(row) + as.integer(row)] = value
  mat
}

> system.time( replicate(100, wide <- with(tall, tapply( value, list(dt,tkr), identity))))
   user  system elapsed 
  11.31    0.03   11.36 

> system.time( replicate(100, wide <- with(tall, pivot(tkr, dt, value))))
   user  system elapsed 
    0.9     0.0     0.9 

Что касается возможных проблем с заказом, не должно быть никаких проблем:

> a <- with(tall, pivot(tkr, dt, value))
> b <- with(tall[sample(nrow(tall)), ], pivot(tkr, dt, value))
> all.equal(a, b)
[1] TRUE
1 голос
/ 15 марта 2011

Несколько замечаний.Пара вопросов SO посвящена тому, как выполнить поворот от высоты к ширине в Sql (ите): здесь и здесь .Я не рассматривал их слишком глубоко, но у меня сложилось впечатление, что делать это в SQL некрасиво, как, например, в вашем SQL-запросе необходимо явно указать все возможные ключи в запросе!(кто-то, пожалуйста, поправьте меня, если я ошибаюсь).Что касается data.table, вы определенно можете выполнять групповые операции очень быстро, но я не понимаю, как вы можете на самом деле преобразовать результат в широкий формат.

Если вы хотите сделать это исключительно в R, я думаю, что tapply здесь скорость, намного быстрее, чем acast из reshape2:

Создайте несколько высоких данных с помощьюнекоторые дыры в нем, чтобы убедиться, что код работает правильно:

tall <- data.frame( dt = rep(1:100, 100),
                     tkr = rep( paste('v',1:100,sep=''), each = 100),
                     value = rnorm(1e4)) [-(1:5), ]


> system.time( replicate(100, wide <- with(tall, tapply( value, list(dt,tkr), identity))))
   user  system elapsed 
   4.73    0.00    4.73 

> system.time( replicate(100, wide <- acast( tall, tkr ~ dt)))
   user  system elapsed 
   7.93    0.03    7.98 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...