通过向量索引访问data.table列?

时间:2018-11-21 10:39:52

标签: r dataframe data.table dynamic-columns

我遇到了问题,但是我在网上找不到令人满意的答案。我想使用start:end向量来定值一个data.frame(对我来说也是一个data.table)。一个例子将阐明我的要求。

假设我有一个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 :(得分:2)

这可以做到:

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

在第二个变体中,我隐藏了循环(隐藏的循环位于另一个位置)。

答案 1 :(得分:0)

尝试此操作,它避免了任何循环或重复应用,并且被矢量化了。这利用了一个事实,即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上执行100万行。