我在R中有一个尺寸为15,000,000 x 140
的tibble。尺寸方面它大约6 gb。
我想检查给定行的第11-40列是否在特定列表中开始。我想得到一个1&的向量0' s然后是15,000,000长。
我可以使用以下方法执行此操作:
subResult <- apply(rawData[,11:40], c(1,2), function(x){substring(x,1,3) %in% c("295", "296", "297", "298", "299")})
result <- apply(subResult, 1, sum)
问题是这太慢了 - 第一行只需要1天就可以了。
有没有办法更快地完成此操作 - 可能直接通过dplyr或data.table?
谢谢!
此处的数据采样仅修剪为第11-40列。
!> head(rawData)
# A tibble: 6 x 30
X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13
<chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
1 39402 39451 3fv3i 19593 fk20 14p4 59304 329fj2 NA NA NA NA NA
2 39422 f203ff vmio2 vo2493 19149 59833 13404 394034 43920 349304 59302 1934 34834
3 3432f32 fe493 43943 H2344 53049 V602 3124 K148 K13 NA NA NA NA
# ... with 17 more variables: X14 <chr>, X15 <chr>, X16 <chr>, X17 <chr>,
# X18 <chr>, X19 <chr>, X20 <chr>, X21 <chr>, X22 <chr>, X23 <chr>,
# X24 <chr>, X25 <chr>, X26 <chr>, X27 <chr>, X28 <chr>, X29 <chr>, X30 <chr>
答案 0 :(得分:3)
我的评论:
substring()
是一个矢量化函数(%in%
)所以,我会这样做:
sapply(rawData[11:40], function(var) {
substring(var, 1, 3) %in% c("295", "296", "297", "298", "299")
})
然后使用rowSums()
代替apply(subResult, 1, sum)
。
答案 1 :(得分:2)
根据说明,可以使用tidyverse
library(tidyverse)
rawData %>%
select(11:40) %>% #select the columns
#convert to logical columns
mutate_all(funs(substring(.,1,3) %in% c("295", "296", "297", "298", "299"))) %>%
reduce('+') %>% #get the rowwise sum
mutate(rawData, newcol = .) # assign a new column to the original data
或者通过将'data.frame'转换为'data.table'(data.table
)来setDT(rawData)
,在.SDcols
中指定感兴趣的列,循环遍历列,转换通过使用OP的条件Reduce
获取每行的sum
并将(:=
)分配给'newcol'
library(data.table)
setDT(rawData)[, newCol := Reduce('+', lapply(.SD, function(x)
substring(x, 1, 3) %chin% c("295", "296", "297", "298", "299"))),
.SDcols = 11:40]
答案 2 :(得分:2)
尝试使用Rcpp
包。
这是一个简单的C ++程序,它接受两个字符串向量,并检查第一个元素的3个字符是否等于第二个元素。因此它将输出大小长度(第一矢量)x长度(第二矢量)的逻辑矩阵。
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
LogicalMatrix IndicatorMatrix(std::vector<std::string> target, std::vector<std::string> tocheck) {
int nrows = target.size();
int ncols = tocheck.size();
LogicalMatrix ind(nrows, ncols);
for(int r=0; r<nrows; r++) {
for(int c=0; c<ncols; c++) {
bool found = target[r].substr(0,3) == tocheck[c];
ind(r,c) = found;
}
}
return ind;
}
之后,您可以将此程序导入R并使用您的IndicatorMatrix
函数,就像它将是R函数对象一样。
library(Rcpp)
sourceCpp("C:/Users/Desktop/indicatorMatrix.cpp")
rep("123456", 15000000) -> x
df <- data.frame(x,x,x,x,x,x,x,x, stringsAsFactors=FALSE)
y <- c("123", "124", "345", "231", "675", "344", "222")
t1 <- Sys.time()
out <- lapply(1:length(df), function(col) {
res <- IndicatorMatrix(unlist(df[,col]), y)
res
})
t2 <- Sys.time()
t2-t1
程序在8列数据框中搜索了8个3字符的字符串,在大约100秒内搜索了15百万行。所以这对你来说可能是正确的方向。