Есть ли пакет R, чтобы помочь в обработке больших данных? - PullRequest
0 голосов
/ 28 июня 2019

Я обрабатываю большой набор данных (после очистки).Затем набор данных обрабатывается для создания матрицы смежности, которой передается logicEval для идентификаторов obs, которые содержат uniqueID.5

При запуске фрагмента кода для создания матрицы смежности процесс занимает огромное количество времени для обработки (а иногда просто останавливается).

Очевидно, это происходит потому, что функцияпроверка каждого из уникальных элементов (n = 10901) и маркировка ИСТИНА / ЛОЖЬ, если они появляются в наблюдении.Пример (значительно уменьшен):

  |Obs_1 |Obs_2 |Obs_3 |Obs_4 |Obs_5 | logEval|
  |:-----|:-----|:-----|:-----|:-----|-------:|
  |TRUE  |FALSE |FALSE |FALSE |FALSE |       1|
  |FALSE |TRUE  |FALSE |FALSE |FALSE |       1|
  |FALSE |FALSE |TRUE  |FALSE |FALSE |       1|
  |FALSE |FALSE |FALSE |TRUE  |FALSE |       1|
  |FALSE |FALSE |FALSE |FALSE |TRUE  |       1|
  |FALSE |FALSE |FALSE |FALSE |TRUE  |       1|
  |FALSE |FALSE |FALSE |FALSE |FALSE |       0|
  |FALSE |FALSE |FALSE |FALSE |FALSE |       0|
  |FALSE |FALSE |TRUE  |FALSE |FALSE |       1|
  |TRUE  |FALSE |FALSE |FALSE |FALSE |       1|
  |FALSE |FALSE |FALSE |FALSE |TRUE  |       1|
  |FALSE |FALSE |FALSE |FALSE |FALSE |       0|
  |FALSE |FALSE |FALSE |FALSE |FALSE |       0|

На самом деле Obs = 43 и существует> 10 0000 сравнений.

Проблема: R падает.Есть ли лучший способ выполнить это без сбоя из-за размера?

Фрагмент кода:

  r
df1<-data.table(col1=sample(500000:500900,700,replace = T),
                col2=sample(500000:500900,700,replace = T),
                col3=sample(500000:500900,700,replace = T),
                col4=sample(500000:500900,700,replace = T),
                col5 = sample(500000:500900,700,replace = T),
                col6 = sample(500000:500900,700,replace = T),
                col7 = sample(500000:500900,700,replace = T),
                col8 = sample(500000:500900,700,replace = T),
                col9 = sample(500000:500900,700,replace = T),
                col10 = sample(500000:500900,700,replace = T),
                col11 = sample(500000:500900,700,replace = T),
                col12 = sample(500000:500900,700,replace = T),
                col13 = sample(500000:500900,700,replace = T),
                col14 = sample(500000:500900,700,replace = T),
                col15 = sample(500000:500900,700,replace = T),
                col16 = sample(500000:500900,700,replace = T),
                col17 = sample(500000:500900,700,replace = T),
                col18 = sample(500000:500900,700,replace = T),
                col19 = sample(500000:500900,700,replace = T),
                col20 = sample(500000:500900,700,replace = T),
                col21 = sample(500000:500900,700,replace = T),
                col22 = sample(500000:500900,700,replace = T),
                col23 = sample(500000:500900,700,replace = T),
                col24 = sample(500000:500900,700,replace = T),
                col25 = sample(500000:500900,700,replace = T),
                col26 = sample(500000:500900,700,replace = T),
                col27 = sample(500000:500900,700,replace = T),
                col28 = sample(500000:500900,700,replace = T),
                col29 = sample(500000:500900,700,replace = T),
                col30 = sample(500000:500900,700,replace = T),
                col31 = sample(500000:500900,700,replace = T),
                col32 = sample(500000:500900,700,replace = T),
                col33 = sample(500000:500900,700,replace = T),
                col34 = sample(500000:500900,700,replace = T),
                col35 = sample(500000:500900,700,replace = T),
                col36 = sample(500000:500900,700,replace = T),
                col37 = sample(500000:500900,700,replace = T),
                col38 = sample(500000:500900,700,replace = T),
                col39 = sample(500000:500900,700,replace = T),
                col40 = sample(500000:500900,700,replace = T),
                col41 = sample(500000:500900,700,replace = T),
                col42 = sample(500000:500900,700,replace = T),
                col43 = sample(500000:500900,700,replace = T))


#find all ids via table
uniqueIDs<-as.character(unique(unlist(df1)))

df1<-data.table(df1)

#creating adjacency matrix
mat <- sapply(uniqueIDs, function(s) apply(dt1, 1, function(x) s %in% x)) 

#clean-up 
colnames(mat) <- uniqueIDs

rownames(mat) <- paste0("row", seq(nrow(dt1)))

mat<-data.table(mat)

mat<-data.table(t(mat))

#apply logical evaluation to count number of TRUE
mat$logEval<-rowSums(mat==TRUE)

Хотите сделать небольшое обновление, чтобы убедиться, что я делаю все в целомцель ясна:

-данат данных имеет x (43) объектов, и каждый объект имеет y (200) nbrids.

  • цель выполнения приведенного выше кода состоит в создании матрицы смежности для идентификатора nbrids (y), отображаемого в столбце .[Например, из уникальных nbrids, появляется ли y (1) в x (i); y (2) ... делает y (900)].

  • Я не имею отношения к х, по сути.конечная цель:

Из уникальных идентификаторов по всей матрице, какие уникальные идентификаторы появляются вместе и как часто [именно поэтому я создаю логический тест для подсчета.n (i) == TRUE]… для тех, кто> 2, я могу фильтровать, поскольку вполне вероятно, что такие строки совместно используют nbrids.

Пример конечной матрицы;

  r

    From        To                Weight
    50012       50056             5
    50012       50032             3
    …
    50063      50090              9

Человек с полным ртом _

Ответы [ 2 ]

2 голосов
/ 28 июня 2019

Если я правильно понимаю ваше требование, то должно работать следующее:

df1 = …
tdf1 = as.data.frame(t(df1))
unique_ids = as.character(unique(unlist(df1)))
# mat = sapply(tdf1, `%in%`, x = unique_ids)
mat = vapply(tdf1, `%in%`, logical(length(unique_ids)), x = unique_ids)
rownames(mat) = unique_ids
colnames(mat) = paste0('row', seq_len(ncol(mat))) # ??? Really?!
log_eval = rowSums(mat)

Обратите внимание, в частности, как mat в моем коде не нужно транспонировать, потому что он уже в правильной ориентации. Закомментированная строка sapply эквивалентна строке vapply, но последняя является более явной и выполняет более строгую проверку типов и, таким образом, менее подвержена ошибкам, если данные неожиданно изменяются. vapply, вероятно, также более эффективен, но с вашими примерами разница не заметна.

Кстати, для генерации случайного df1 вы можете сократить свой 43-строчный код до

df1 = as.data.frame(replicate(43, sample(500000 : 500900, 700, replace = TRUE)))
1 голос
/ 29 июня 2019

2-е редактирование:

Эти параметры, похоже, соответствуют ожидаемым результатам при редактировании. Оба варианта полагаются на самостоятельные объединения, чтобы посмотреть, какие комбинации есть. Первый вариант использует lapply() для самостоятельного объединения одного столбца за раз, в то время как последний melt() с, а затем сам присоединяется ко всему набору данных. Для небольших наборов данных lapply() медленнее, но при попытке 7000 строк оно все же прошло, тогда как расплавление и самостоятельное соединение создали слишком большой фрейм данных.

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

library(data.table)

# generate data -----------------------------------------------------------
set.seed(1234)
dt1<- data.table(replicate(43, sample(500000:500900,700, replace = TRUE)))

rbindlist(
  lapply(dt1
       , function(x) {
         nbrid_dt = data.table(nbrid = unique(x))

         nbrid_dt[nbrid_dt
                  , on = .(nbrid < nbrid)
                  , j = .(From = x.nbrid, To = i.nbrid)
                  , nomatch = 0L
                  , allow.cartesian = T]
       }
       )
  )[, .N, keyby = .(From, To)]

          From     To  N
     1: 500000 500001 11
     2: 500000 500002 11
     3: 500000 500003  7
     4: 500000 500004  9
     5: 500000 500005 13
    ---                 
405446: 500897 500899 12
405447: 500897 500900 10
405448: 500898 500899 13
405449: 500898 500900 12
405450: 500899 500900  9

#all at once

molten_dt <- unique(melt(dt1))
setkey(molten_dt, variable)

molten_dt[molten_dt
          , on = .(value < value
                   ,variable = variable
                    )
          , .(From = x.value, To = i.value)
          , allow.cartesian = TRUE
          , nomatch = 0L
          ][!is.na(From), .N, keyby = .(From, To)]

Оригинал: Я не до конца слежу, но если вы в основном следите за количеством подсчетов в своих 43 столбцах, может быть полезно собрать / расплавить данные.

molten_dt <- melt(dt1)

molten_dt[, N := length(unique(variable)), by = value]

      variable  value  N
   1:       V1 500102  9
   2:       V1 500560  8
   3:       V1 500548  9
   4:       V1 500561 12
   5:       V1 500775  9
  ---                                    
8596:      V43 500096  7
8597:      V43 500320  6
8598:      V43 500205 14
8599:      V43 500711  7
8600:      V43 500413 11

#or you can aggregate instead of mutate-in-place

molten_dt[, .(N = length(unique(variable))), by = value]

      value  N
  1: 500102  9
  2: 500560  8
  3: 500548  9
  4: 500561 12
  5: 500775  9
 ---          
897: 500753  4
898: 500759  4
899: 500816  6
900: 500772  4
901: 500446  2

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

Данные:

set.seed(1234)
dt1<- as.data.table(replicate(43, sample(500000 : 500900, 200, replace = TRUE)))
#h/t for @Konrad for the quick way to make 43 columns

1-е редактирование: Если вас интересует только счет каждого значения, вы можете сделать следующее:

mat_data <- matrix(replicate(43, sample(500000 : 500900, 700, replace = TRUE)), ncol = 43)

table(unlist(apply(mat_data, 2, unique)))

Это самый быстрый подход, но проблема в том, что вы теряете информацию о том, какой столбец предоставил информацию.

Unit: milliseconds
           expr     min      lq     mean   median       uq      max neval
 melt_and_count 53.3914 53.8926 57.38576 55.95545 58.55605  79.2055    20
  table_version 11.0566 11.1814 12.24900 11.56760 12.82110  16.4351    20
 vapply_version 63.1623 64.8274 69.86041 67.84505 71.40635 108.2279    20
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...