通过向量索引访问 data.table 列?
Access data.table columns through vector indexes?
我遇到了一个问题,但我在网上找不到满意的答案。我想使用 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
解决方案会更好)
谢谢
这样做就可以了:
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
在第二个变体中,我隐藏了循环(隐藏循环在另一个地方)。
试试这个,它避免了任何循环或 lapply 并且是矢量化的。这利用了 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)
在我的 MacBook Pro 上执行 100 万行大约需要 5 秒。
我遇到了一个问题,但我在网上找不到满意的答案。我想使用 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
解决方案会更好)
谢谢
这样做就可以了:
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
在第二个变体中,我隐藏了循环(隐藏循环在另一个地方)。
试试这个,它避免了任何循环或 lapply 并且是矢量化的。这利用了 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)
在我的 MacBook Pro 上执行 100 万行大约需要 5 秒。