применить функцию для итерации по фрейму данных и создания столбцов на основе столбца индекса - PullRequest
0 голосов
/ 05 ноября 2019

Итак, позвольте мне описать данные:

  • abc и xyz являются метриками.
  • hit в основном это индексный номер, например:
    • значение попадания 3 означает соответствующее значение в abc3 и xyz3
    • попадание 4 означает abc4, xyz4

Данные

dat <- data.frame( abc1=c(7, 0, 7), 
                   abc2=c(5, 10, 20), 
                   abc3=c(0, 0, 10), 
                   abc4=c(3, 5, 19), 
                   abc5=c(2, 2, 0), 
                   abc6=c(2, 26, 0),
                   xyz1=c(0, 2, 0),
                   xyz2=c(1, 1, 6),
                   xyz3=c(8, 2, 0),
                   xyz4=c(6, 3, 5),
                   xyz5=c(9, 2, 2),
                   xyz6=c(4, 0, 0),
                   hit=c(3, 4, 4))

Что мне нужно сделать, это найти abc и xyz до попаданий и после попаданий. Цикл ниже для for хорошо работает для небольших наборов данных, но еслиданные пересекают 100 тыс. строк, цикл выполняется, по-видимому, вечно.

for (c in c('abc','xyz')){
  for (i in 1:nrow(dat)){
    for (m in -2:2){

      dat[[paste(c,'hit', m)]][i] = dat[i,paste(c, dat$hit[i]-m, sep = "")]
    }
  }
}

В выходном файле 'abc hit 0' для строки 1 относится к: hit = 3, который, в свою очередь, выбираетзначение в abc3 и присваивает abc hit 0 .

abc hit -1 переводится в hit = 3-1 = 2, что указывает на abc2 и xyz2

Я знаю, что 3 для циклов - плохая идея. Пожалуйста, помогите мне улучшить код, используя функцию apply или любой другой способ, который сокращает время выполнения.

1 Ответ

0 голосов
/ 05 ноября 2019

Вы, кажется, перевернули 'm' в цикле for: он работает от -2 до 2, но затем вы получите dat$hit - m - это вычитание, что вы хотели? Или это должно быть dat$hit + m?

Вы могли бы сделать что-то вроде ниже - я не проверял это на больших наборах данных, но действительно попробую:

dat1 <- do.call(rbind, 
                lapply(split(dat, 1:NROW(dat)), 
                       function(x) {
                          z <- x[paste0('abc', x$hit + 2:-2)]; 
                          names(z) <- paste0('abc', -2:2); 
                          z 
                       }
                ))

split функция дает вам строки информационного кадра, успешно сохраняя имена столбцов, и затем вы можете использовать функцию lapply для построчной работы.

Вы можете искать соответствующие столбцы каждой строки. добавив от -2 до 2 к hit.

Затем вы объедините список результатов обратно в кадр данных.

Обновление : это быстрее, чем вышеоколо 30% для строк 90К:

dat1 <- t(sapply(split(dat, 1:NROW(dat)), 
                       function(x) unname(x[paste0('abc', x$hit + 2:-2)])  
                ))
dat1 <- as.data.frame(dat1)
colnames(dat1) <- paste0('abc', -2:2)
...