Доступ к столбцам data.table через векторные индексы? - PullRequest
0 голосов
/ 21 ноября 2018

Я застрял с проблемой, но я не могу найти удовлетворительных ответов в Интернете.Я хотел бы оценить data.frame (также data.table, это хорошо для меня), используя векторы start: end.Пример пояснит, что я спрашиваю.

Предположим, у меня есть data.frame, подобный следующему:

df <- data.frame(col_1 = rep(0, 3), col_2 = rep(0, 3), col_3 = rep(0, 3), col_4 = rep(0,3))
df
  col_1 col_2 col_3 col_4
1     0     0     0     0
2     0     0     0     0
3     0     0     0     0

И предположим, у меня есть два вектора:

indexesStart <- c(1, 2, 1)
indexesEnd   <- c(2, 4, 3)

Я хотел бы повысить до 1 все значения в диапазоне, указанном векторами по строкам.Вывод должен быть следующим:

  col_1 col_2 col_3 col_4
1     1     1     0     0
2     0     1     1     1
3     1     1     1     0

Я пробовал что-то вроде этого:

df[ , indexesStart:indexesEnd] <- 1

Но это не работает, просто нужно indexesStart[1]:indexesEnd[1] и повторить это для всех строк,

Я должен избегать циклов цикла , потому что мой реальный фрейм данных содержит миллионы строк и он слишком медленный.Любая помощь приветствуется (решение data.table будет еще лучше)

Спасибо

Ответы [ 2 ]

0 голосов
/ 21 ноября 2018

Попробуйте, это позволяет избежать зацикливания или неудач и векторизовано.Это использует тот факт, что data.frame действительно является списком.

impute <- function(lst, start, end){ lst[start:end] <- 1; lst }

fill <- function(df, start, end){
  cols <- names(df)
  lst <- as.list(as.data.frame(t(df)))
  res <- as.data.frame(t(Vectorize(impute)(lst, start, end)))
  names(res) <- names(df)
  row.names(res) <- row.names(df)
  res
}

res <- fill(df, indexesStart, indexesEnd)

Требуется около 5 секунд, чтобы сделать миллион строк на моем MacBook Pro.

0 голосов
/ 21 ноября 2018

Это будет сделано:

df <- data.frame(col_1=rep(0,3),col_2=rep(0,3),col_3=rep(0,3),col_4=rep(0,3))
indexesStart <- c(1, 2, 1)
indexesEnd   <- c(2, 4, 3)

for (i in 1:nrow(df)) df[i, indexesStart[i]:indexesEnd[i]] <- 1

df

Вот еще один метод, использующий двухколоночную матрицу в качестве индекса:

I <- do.call(rbind, lapply(1:length(indexesStart), function(i) cbind(i, indexesStart[i]:indexesEnd[i])))
df[I] <- 1

Во втором варианте я скрыл цикл (и скрытый циклнаходится в другом месте).

...