Как применить таблицу к нескольким столбцам с data.table?

Немногие другие наблюдения

  • Как указано в @dasblinkenlight выше, Hadoop Bytes.toBytes(c); внутренне вызывает String.getBytes("UTF-8")
  • Вариантный метод String.getBytes(), который принимает набор символов поскольку входной сигнал быстрее, чем тот, который не принимает никакого набора символов. Поэтому для данной строки getBytes("UTF-8") будет быстрее, чем getBytes(). Я тестировал это на своей машине (Windows8, JDK 7). Выполните две петли, одна с getBytes("UTF-8") и другая с getBytes() последовательно в равных итерациях.
        long ts;
        String c = "sgfrt34tdfg34";
    
        ts = System.currentTimeMillis();
        for (int k = 0; k < 10000000; k++) {
            c.getBytes("UTF-8");
        }
        System.out.println("t1->" + (System.currentTimeMillis() - ts));
    
        ts = System.currentTimeMillis();
        for (int i = 0; i < 10000000; i++) { 
            c.getBytes();
        }
        System.out.println("t2->" + (System.currentTimeMillis() - ts));
    

это дает:

t1->1970
t2->2541

, и результаты одинаковы, даже если вы меняете порядок выполнения цикла. Чтобы уклониться от любых оптимизаций JIT, я бы предложил запустить тесты по отдельным методам, чтобы подтвердить это (как это предложил @Peter Lawrey выше)

  • Таким образом, Bytes.toBytes(c) всегда будет быстрее, чем String.getBytes()
2
задан Brian Tompsett - 汤莱恩 16 January 2019 в 21:48
поделиться

4 ответа

Хорошо, я нашел решение, немного запутанное:

prueba[, lapply(.SD, function(x) as.list( table(factor(
is.na(x), levels=c(F,T)))) ), .SDcols=c("aa","bb", "cc")]

Должен быть более легкий путь.

0
ответ дан skan 16 January 2019 в 21:48
поделиться

Возможно, используйте table:

prueba[, table(is.na(.SD), names(.SD)[col(.SD)]), .SDcols=aa:cc]

        aa bb cc
  FALSE  7  5  5
  TRUE   0  2  2

По сути, это относится к матрице.

Некоторые альтернативы:

prueba[, table(is.na(.SD), rep(names(.SD), each=.N)), .SDcols=aa:cc]

melt(prueba[, aa:cc])[, table(is.na(value), variable)]
0
ответ дан Frank 16 January 2019 в 21:48
поделиться

Вот еще одно предложение, которое должно быть достаточно общим. Во-первых, составьте таблицу сопряженности на основе требований. Затем преобразуйте вывод таблицы в список и rbindlist все результаты вместе. Наконец, замените NA на 0 отсчетов.

output <- prueba[, rbindlist(
        lapply(.SD, function(x) as.list(table(is.na(x)))), 
        fill=TRUE, 
        idcol=TRUE), 
    .SDcols=aa:cc]

output[, lapply(.SD, function(x) replace(x, is.na(x), 0L))]

вывод:

   .id FALSE TRUE
1:  aa     7    0
2:  bb     5    2
3:  cc     5    2
<час>

редактирование: добавление еще одного общего подхода:

#build and flatten contingency table
tab <- prueba[, as.list(unlist(lapply(.SD, function(x) table(is.na(x))))),
    .SDcols=aa:cc]

#melt, split original column names and then pivot
dcast(
    melt(tab, measure.vars=names(tab))[, 
        c("V1","Factor") := tstrsplit(variable, split="\\.")],
    Factor ~ V1, 
    function(x) x[1L], 
    fill=0L) 

вывод:

   Factor aa bb cc
1:  FALSE  7  5  5
2:   TRUE  0  2  2
<час>

Изменить: добавить время

set.seed(0L)
sz <- 1e6
nc <- 10
DT <- as.data.table(matrix(sample(c(NA_integer_, 1L:10L), sz*nc, TRUE), ncol=nc))
setnames(DT, paste0("C", 1L:nc))
cols <- names(DT)

mtd1 <- function() {
    DT[, table(is.na(.SD), names(.SD)[col(.SD)]), .SDcols=cols]
}

mtd2 <- function() {
    DT[, table(is.na(.SD), rep(names(.SD), each=.N)), .SDcols=cols]
}

mtd3 <- function() {
    melt(DT[, ..cols], measure.vars=cols)[, table(is.na(value), variable)]
}

mtd4 <- function() {
    tab <- DT[, as.list(unlist(lapply(.SD, function(x) table(is.na(x))))),
        .SDcols=cols]

    dcast(melt(tab, measure.vars=names(tab))[, c("V1","Factor") := tstrsplit(variable, split="\\.")],
        Factor ~ V1, function(x) x[1L], fill=0L)
}

mtd5 <- function() {
    output <- DT[, rbindlist(lapply(.SD, function(x) as.list(table(is.na(x)))), fill=TRUE, idcol=TRUE),
        .SDcols=cols]

    output[, lapply(.SD, function(x) replace(x, is.na(x), 0L))]
}

library(microbenchmark)
microbenchmark(mtd1(), mtd2(), mtd3(), mtd4(), mtd5(), times=3L)

время:

Unit: seconds
   expr      min       lq     mean   median       uq      max neval cld
 mtd1() 5.044369 5.049252 5.086534 5.054135 5.107617 5.161100     3   b
 mtd2() 5.106796 5.110014 5.474269 5.113232 5.658005 6.202778     3   b
 mtd3() 2.395127 2.461463 2.509938 2.527799 2.567344 2.606888     3  a 
 mtd4() 2.138672 2.142300 2.145895 2.145927 2.149506 2.153084     3  a 
 mtd5() 2.113367 2.175346 2.228162 2.237325 2.285560 2.333794     3  a 
0
ответ дан chinsoon12 16 January 2019 в 21:48
поделиться

Вот подход с базой R:

rbind(tmp <- colSums(is.na(prueba[ , -"YEAR"])), nrow(prueba) - tmp)
#      aa bb cc
# [1,]  0  2  2
# [2,]  7  5  5
0
ответ дан Sven Hohenstein 16 January 2019 в 21:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: