alk*_*lki 3 r matrix dataframe
我试图在两列矩阵中操纵列数据并将其作为data.frame输出.
我所拥有的矩阵采用这种格式,其中起始列和结束列中的值都在增加且不重叠.此外,始终条目总是比结束条目多.
假设我从这个矩阵开始:
# Start End
# [1,] 1 6
# [2,] 2 9
# [3,] 3 15
# [4,] 7 NA
# [5,] 8 NA
# [6,] 11 NA
# [7,] 12 NA
# [8,] 14 NA
Run Code Online (Sandbox Code Playgroud)
我希望这个double for循环输出一个data.frame,它将所有Start值分组为小于End值并将其与该End值相关联.
为了澄清我想输出这个:
# Start End
# 1 1,2,3 6
# 2 7,8 9
# 3 11,12,14 15
Run Code Online (Sandbox Code Playgroud)
我尝试了一个双循环,但我需要更快的东西,因为我想在更大的矩阵~5 MB上使用此方法.
start_end <- matrix(c(1, 6, 2, 9, 3, 15, 7, NA, 8, NA, 11, NA, 12, NA, 14, NA),
nrow=8,
ncol=2)
# of non NA rows in column 2
non_nacol <- sum(is.na(start_end[,2]))
sorted.output <- data.frame(matrix(NA, nrow = nrow(start_end), ncol = 0))
sorted.output$start <- 0
sorted.output$end <- 0
#Sort and populate data frame
for (k in 1:non_nacol) {
for (j in 1:nrow(start_end)) {
if (start_end[j,1]<start_end[k,2]) {
S <- (start_end[j,1])
E <- (start_end[k,2])
sorted.output$start[j] <- S
sorted.output$end[j] <- E
}
}
}
Run Code Online (Sandbox Code Playgroud)
谢谢您的帮助!
这里有一个解决方案围绕建成findInterval(),split()以及paste():
m <- matrix(c(1,2,3,7,8,11,12,14,6,9,15,NA,NA,NA,NA,NA),ncol=2,dimnames=list(NULL,c('Start','End')));
data.frame(Start=sapply(split(m[,'Start'],findInterval(m[,'Start'],na.omit(m[,'End']))),paste,collapse=','),End=na.omit(m[,'End']));
## Start End
## 0 1,2,3 6
## 1 7,8 9
## 2 11,12,14 15
Run Code Online (Sandbox Code Playgroud)
编辑:您遇到的问题是由于在您的实际数据中输入End值之间的某些间隔不包含任何输入Start值.我上面的解决方案错误地从输出Start向量中省略了那些间隔,这导致与输出向量的长度不匹配End.
这是一个固定的解决方案:
end <- na.omit(m[,'End']);
data.frame(Start=unname(sapply(split(m[,'Start'],findInterval(m[,'Start'],end))[as.character(0:c(length(end)-1))],paste,collapse=',')),End=end);
## Start End
## 1 1,2,3 6
## 2 7,8 9
## 3 11,12,14 15
Run Code Online (Sandbox Code Playgroud)
这是一个空间隔的测试矩阵的演示:
m <- matrix(c(1,2,3,11,12,14,6,9,15,NA,NA,NA),ncol=2,dimnames=list(NULL,c('Start','End')));
m;
## Start End
## [1,] 1 6
## [2,] 2 9
## [3,] 3 15
## [4,] 11 NA
## [5,] 12 NA
## [6,] 14 NA
end <- na.omit(m[,'End']);
data.frame(Start=unname(sapply(split(m[,'Start'],findInterval(m[,'Start'],end))[as.character(0:c(length(end)-1))],paste,collapse=',')),End=end);
## Start End
## 1 1,2,3 6
## 2 9
## 3 11,12,14 15
Run Code Online (Sandbox Code Playgroud)
如您所见,对于空间隔,导致输出Start向量的值是空字符串,我认为这是一个明智的结果.如果需要,您可以在以后更改结果.
最后,这是使用您发布到Dropbox的真实数据的演示:
m <- read.table('start_end.txt',col.names=c('Start','End'));
head(m);
## Start End
## 1 11165 10548
## 2 12416 11799
## 3 12466 11900
## 4 12691 11976
## 5 12834 13336
## 6 13320 14028
end <- na.omit(m[,'End']);
system.time({ out <- data.frame(Start=unname(sapply(split(m[,'Start'],findInterval(m[,'Start'],end))[as.character(0:c(length(end)-1))],paste,collapse=',')),End=end); });
## user system elapsed
## 21.234 0.015 21.251
head(out);
## Start End
## 1 10548
## 2 11165 11799
## 3 11900
## 4 11976
## 5 12416,12466,12691,12834,13320 13336
## 6 13425,13571,13703,13920 14028
nrow(out);
## [1] 131668
Run Code Online (Sandbox Code Playgroud)