Операции со строками в data.table

Я пытаюсь выполнить простую сумму и среднее значение по строкам, используя data.table, но Я получаю неожиданные результаты. Я следил за справкой в ​​разделе 2 FAQ. руководство для data.table. Я нашел способ, который работает, но я не уверен, почему этого метода в разделе 2 FAQ нет. Этот метод дает мне неправильный результат (т. е. дает мне значение первого столбца):

dt[, genesum:=lapply(.SD,sum), by=gene]
head(dt)

      gene      TCGA_04_1348      TCGA_04_1362   genesum  
  1:    A1BG          0.94565          0.70585  0.94565   
  2: A1BG-AS          0.97610          1.15850  0.97610   
  3:    A1CF          0.00000          0.02105  0.00000   
  4:   A2BP1          0.00300          0.04150  0.00300   
  5:   A2LD1          4.57975          5.02820  4.57975  
  6:     A2M         60.37320         36.09715 60.37320 

и это дает мне желаемый результат

dt[, genesum:=apply(dt[,-1, with=FALSE],1, sum)]
head(dt)

       gene     TCGA_04_1348       TCGA_04_1362 genesum
  1:    A1BG          0.94565          0.70585  1.65150
  2: A1BG-AS          0.97610          1.15850  2.13460
  3:    A1CF          0.00000          0.02105  0.02105
  4:   A2BP1          0.00300          0.04150  0.04450
  5:   A2LD1          4.57975          5.02820  9.60795
  6:     A2M         60.37320         36.09715 96.47035

У меня есть еще много столбцов и строк, это всего лишь подмножество. Это как-то связано с тем, как я установил ключ?

tables()
 NAME        NROW    MB COLS                                               KEY                                             
 [1,] dt     20,785  2  gene,TCGA_04_1348_01A,TCGA_04_1362_01A,genesum    gene

person sahir    schedule 08.02.2014    source источник


Ответы (2)


Несколько вещей:

  1. dt[, genesum:=lapply(.SD,sum), by=gene] и dt[, genesum:=apply(dt[ ,-1],1, sum)] совершенно разные.

    • dt[, genesum:=lapply(.SD,sum), by=gene] перебирает столбцы таблицы .SD data.table и суммирует их.

    • dt[, genesum:=apply(dt[, -1], 1, sum)] перебирает строки (т.е. apply(x, 1, function) применяет function к каждой строке в x

  2. Я думаю, вы можете получить то, что хотите, позвонив rowSums, например:

    dt[, genesum := rowSums(dt[, -1])]
    

Это то, что вам нужно?

person Steve Lianoglou    schedule 08.02.2014
comment
Я вижу разницу сейчас. С точки зрения эффективности, нет ли разницы между apply и rowSums? - person sahir; 09.02.2014
comment
@sahir: я считаю, что rowSums должен быть быстрее, так как я считаю, что он позволяет избежать цикла в R, однако он также создаст копию своего ввода, чтобы преобразовать его в матрицу, если это еще не так. - person Steve Lianoglou; 14.02.2014
comment
Как я могу написать такие функции, как rowSums... скажем, rowMedian? - person Indranil Gayen; 28.02.2017
comment
@IndranilGayen: чтобы избежать зацикливания в R, вам придется написать его на C/C++. Взгляните на пакет matrixStats, он предоставляет множество таких операций со строками* и столбцами*, и они re сделано быстро, делегируя C. (я связался с github вместо CRAN, чтобы вам было легче просматривать исходный код) - person Steve Lianoglou; 01.03.2017

Вот одна альтернатива (на основе этого вопроса SO):

dt[ ,  genesum := sum(.SD[, -1, with=FALSE]), by = 1:NROW(dt) ]

другая альтернатива:

# OR... you can create a column with row positions and apply your function by row
dt[, rowpos := .I]
dt[ ,  genesum := sum(.SD[, -1, with=FALSE]), by = rowpos]
person rafa.pereira    schedule 06.06.2016