2016-06-08 7 views
3

[data.table_1.9.6] Вопрос в том, что я пытаюсь построить похожие на olap объекты в схеме звездочек подобный формат данных, то есть большая таблица фактов и несколько мета-таблиц. Я строй функции обертки вокруг data.table присоединиться с последующей агрегацией в цепи, так:r data.table функция обертка вокруг ad-hoc соединения (с агрегацией в цепочке)

# dummy data 
dt1 = data.table(id = 1:5, x=letters[1:5], a=11:15, b=21:25) 
dt2 = data.table(k=11:15, z=letters[11:15]) 

# standard data.table query with ad-hoc key -> works fine 
dt1[dt2, c("z") := .(i.z), with = F, 
    on = c(a="k")][, .(m = sum(a, na.rm = T), 
        count = .N), by = c("z")] 

# wrapper function with setkey -> works fine 
agg_foo <- function(x, meta_tbl, x_key, meta_key, agg_var) { 
    setkeyv(x, x_key) 
    setkeyv(meta_tbl, meta_key) 
    x[meta_tbl, (agg_var) := get(agg_var)][,.(a_sum = sum(a, na.rm=T), 
              count = .N), 
             by = c(agg_var)] 
    x[, (agg_var) := .(NULL)] 
    } 

# call function (works fine) 
agg_foo(x=dt1, meta_tbl=dt2, x_key="a", meta_key="k",agg_var="z") 

# wrapper function with ad-hoc key -> does not work 
agg_foo_ad_hoc <- function(x, meta_tbl, x_key, meta_key, agg_var) { 
    x[meta_tbl, (agg_var) := get(agg_var), 
    on = c(x_key = meta_key)][,.(a_sum = sum(a, na.rm=T), 
           count = .N), by = c(agg_var)] 
    x[, (agg_var) := .(NULL)] 
    } 

# call function (causes error) 
agg_foo_ad_hoc(x=dt1, meta_tbl=dt2, x_key="a", meta_key="k",agg_var="z") 

Error in forderv(x, by = rightcols) : 
    'by' value -2147483648 out of range [1,4] 

я думаю, что я должен предоставить Времнный «на» параметре по-другому. Я попытался включить = c (get (x_key) = meta_key), но затем он жалуется на неожиданные скобки. Я мог бы пойти с установленной версией функции, которая работает, но мне интересно, эффективно ли это, если функция будет работать на разных мета-таблицах, в зависимости от того, какой атрибут для агрегации используется и тем самым постоянно переустанавливает ключ. или всегда является предпочтительным? таблица фактических фактов (x здесь) имеет> 30 миллионов строк.

+2

Вы можете проверить [data.cube] (https://github.com/jangorecki/data.cube) пакет, который определяет тип OLAP куба R данных, на основе набора данных. В пакете есть класс 'cube', который является моделью звезды. В devel branch * data.cube-oop * появился новый класс 'data.cube', который представляет собой смесь схемы звезд и снежинок, описанную в [этом вопросе SO] (https://stackoverflow.com/questions/35472639/ звезда-схемы нормализованы-размеры-денормализованный-иерархия уровня-ключи). Он автоматически подразделяется на доступные размеры и сохраняет данные в кубе нормализованными. – jangorecki

+0

@ jangorecki: Я знаю о вашем пакете. уже смотрел в нее в прошлом. спасибо за подсказку в любом случае! Я также с удовольствием перейду через его источник github, если он не будет заблокирован корпоративными ИТ. но есть ли только реализация data.table? – Triamus

+2

Фактическое восходящее репо находится на [gitlab.com/jangorecki/data.cube](https://gitlab.com/jangorecki/data.cube), поэтому вы можете попробовать там. Реализация основана на 'data.table' и [big.data.table] (https://github.com/jangorecki/big.data.table) для таблицы фактов (и только частично для класса' cube'). Последний позволяет распределять таблицу фактов по нескольким машинам, устранять ограничения на память и разрешать параллельные запросы, способные эффективно обрабатывать большие данные OLAP. – jangorecki

ответ

2

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

agg_foo_ad_hoc <- function(x, meta_tbl, x_key, meta_key, agg_var) { 
    x[meta_tbl, (agg_var) := get(agg_var), 
    on = setNames(meta_key, x_key)][,.(a_sum = sum(a, na.rm=T), 
             count = .N), by = c(agg_var)] 
    x[, (agg_var) := .(NULL)] 
} 
+0

Есть ли у вас мнение о дизайне функции, то есть, нужно ли предпочтение уставки по специальному ключу? – Triamus

+2

@Triam в настоящее время я использую 'on' почти исключительно. Это более гибко, и мне нравится знать, что я делаю в каждой операции, а не использовать 'setkey' в какой-то другой части кода, а затем помнить, что я это сделал. Единственный случай, когда я буду использовать 'setkey', - это если мне нужно сделать несколько соединений/поисков в строке на одном и том же ключе. – eddi