我正在尝试在R中处理一个20 GB的数据文件。我有16 GB的RAM和i7处理器。我正在使用以下方式阅读数据:
y<-read.table(file="sample.csv", header = TRUE, sep = ",", skip =0, nrows =50000000)
数据集'y'如下:
id feature
21 234
21 290
21 234
21 7802
21 3467
21 234
22 235
22 235
22 1234
22 236
22 134
23 9133
23 223
23 245
23 223
23 122
23 223
以上是示例数据集,它显示了特定id的不同功能。我想计算在y中为id生成的另一个数据集x中列出的特定功能的次数。
数据集x如下:
id feature
21 234
22 235
23 223
我想要的最终输出如下:
id feature_count
21 3
22 2
23 3
我们看到234次发生了21次,其中235次发生了22次,223次发生了23次。
为此我尝试获取新id开始的位置:(例如上面样本的第1,第7和第12位置),然后使用for循环计算一个特征,如下所示:
positions=0
positions[1]=1
j=2
for(i in 1:50000000){
if(y$id[i]!=y$id[i+1]){
positions[j]=i+1
j=j+1
}
}
由于数据量巨大,循环需要花费大量时间。(对于5000万行,上面提到的配置PC需要321秒,我有3亿行)。
for(i in 1 :length(positions)){
for(j in positions[i]:positions[i+1]){
if(y$feature[j]==x$feature[i]){
feature_count[i]=feature_count[i]+1
}
}
}
是否有任何R功能可以在更快的时间内为我集体完成这项工作。 使用“positions [i]:positions [i + 1]”递增循环也会在for循环中抛出一个错误,表示NA参数。请建议一个正确的方法来做到这一点。
答案 0 :(得分:1)
我建议使用data.table包(fread
非常快!),然后设置一个循环,循环读取文件一次读取并存储特征计数总和。以下是我用于循环文件的函数的一些改编行,它可能不会按原样运行,但你可以知道该做什么
require(data.table)
LineNu <- as.numeric(gsub(" .+","",system2("wc",paste("-l",your.file,sep=" "),stdout=TRUE, stderr=TRUE)))
DT <- fread(your.file,nrows=50000000,sep=",",header=TRUE)
KEEP.DT <- DT[,list("feature"=sum(length(feature))),by=id]
rm(DT) ; gc()
Starts <- c(seq(50000000,LineNu,by=50000000),LineNu)
for (i in 2:(length(Starts)-1)) {
cat(paste0("Filtering next 50000000 lines ", i, " of ",length(Starts)-1, " \n"))
DT <- fread(your.file,skip=Starts[i],nrows=ifelse(50000000*(i-1) < Starts[length(Starts)],50000000,(50000000*(i-1)) - Starts[length(Starts)]),sep=",",header=FALSE)
DT[,list("feature"=sum(length(feature))),by=id]
KEEP.DT <- rbind(KEEP.DT,DT)
rm(DT) ; gc()
}
您可能需要重做DT [sum(length)]部分,因为某些id可能会以不同的块读入。
答案 1 :(得分:1)
我承认我并不真正理解它的编写方式,但听起来像“data.table”就是这样,你应该研究.N
函数。如前所述fread
会比read.csv
好得多,所以我假设您已将数据读入名为“DT”的data.table
。
这是一个小问题:
DT <- data.table(id = c(rep(21, 6), rep(22, 5), 23, 23),
feature = c(234, 290, 234, 7802, 3467, 234, 235,
235, 1234, 236, 134, 9133, 223))
DT
# id feature
# 1: 21 234
# 2: 21 290
# 3: 21 234
# 4: 21 7802
# 5: 21 3467
# 6: 21 234
# 7: 22 235
# 8: 22 235
# 9: 22 1234
# 10: 22 236
# 11: 22 134
# 12: 23 9133
# 13: 23 223
如果您只想计算每个独特功能的数量,可以这样做:
DT[, .N, by = "id,feature"]
# id feature N
# 1: 21 234 3
# 2: 21 290 1
# 3: 21 7802 1
# 4: 21 3467 1
# 5: 22 235 2
# 6: 22 1234 1
# 7: 22 236 1
# 8: 22 134 1
# 9: 23 9133 1
# 10: 23 223 1
如果您想要计算第一个“功能”,按“id”,您可以使用:
DT[, .N, by = "id,feature"][, .SD[1], by = "id"]
# id feature N
# 1: 21 234 3
# 2: 22 235 2
# 3: 23 9133 1
如果您希望通过“id”获得最常出现的“功能”(这与上面的结果相同,在这种情况下),您可以尝试以下操作:
DT[, .N, by = "id,feature"][, lapply(.SD, function(x) x[which.max(N)]), by = "id"]
根据您的新说明,这似乎更容易。
只需merge
您的数据集和aggregate
计数。再次,快速做“data.table”:
DTY <- data.table(y, key = "id,feature")
DTX <- data.table(x, key = "id,feature")
DTY[DTX][, .N, by = id]
# id N
# 1: 21 3
# 2: 22 2
# 3: 23 3
或者:
DTY[, .N, by = key(DTY)][DTX]
# id feature N
# 1: 21 234 3
# 2: 22 235 2
# 3: 23 223 3
这假设“x”和“y”定义如下:
x <- structure(list(id = 21:23, feature = c(234L, 235L, 223L),
counts = c(3L, 2L, 3L)), .Names = c("id", "feature", "counts"),
row.names = c(NA, -3L), class = "data.frame")
y <- structure(list(id = c(21L, 21L, 21L, 21L, 21L, 21L, 22L, 22L,
22L, 22L, 22L, 23L, 23L, 23L, 23L, 23L, 23L), feature = c(234L,
290L, 234L, 7802L, 3467L, 234L, 235L, 235L, 1234L, 236L, 134L,
9133L, 223L, 245L, 223L, 122L, 223L)), .Names = c("id", "feature"),
class = "data.frame", row.names = c(NA, -17L))
答案 2 :(得分:0)
对于你的例子:
apply(sign(table(y)), 1, sum)
21 22 23
4 4 2
答案 3 :(得分:0)
table()怎么样?
> set.seed(5)
> ids <- sample(1:3, 12, TRUE)
> features <- sample(1:4, 12, TRUE)
> cbind(ids, features)
ids features
[1,] 1 2
[2,] 3 3
[3,] 3 2
[4,] 1 1
[5,] 1 2
[6,] 3 4
[7,] 2 3
[8,] 3 4
[9,] 3 4
[10,] 1 3
[11,] 1 1
[12,] 2 1
> table(ids, features)
features
ids 1 2 3 4
1 2 2 1 0
2 1 0 1 0
3 0 1 1 3
因此,例如,功能4在ID 3中出现3次。
编辑:您可以使用as.data.frame()来&#34;展平&#34;表格得到:
> as.data.frame(table(ids, features))
ids features Freq
1 1 1 2
2 2 1 1
3 3 1 0
4 1 2 2
5 2 2 0
6 3 2 1
7 1 3 1
8 2 3 1
9 3 3 1
10 1 4 0
11 2 4 0
12 3 4 3