R - 创建具有非空交集的切割间隔
R - Create cut-like intervals with non-empty intersection
我有一个数据框 df
,其中有一列名为 x1
,其值介于 -5 和 +5 之间。我试图为 df
的每一行分配一个关于 x1
值的间隔。函数 cut
允许我这样做 :
cut(df$x1,c(-5,-4,-3,-2,-1,0,1,2,3,4,5))
然后我可以使用 by
将 df
拆分为 10 data.frames
。不幸的是,我想要分配间隔,例如 -5 到 -3.95、-4.05 到 -2.95、-3.05 到 -1.95 等等,这意味着:
- 4.06将在区间3.95-5.05
- 4.05将在区间3.95-5.05和2.95-4.05
- 4.04将在区间3.95-5.05和2.95-4.05
- 3.94将在区间2.95-4.05
这意味着在使用 by
之后,我将有 10 个数据帧,其中 2 个数据帧中有一些元素。
我的问题的下一部分将涉及 0 附近的值:间隔不应包含负值和正值,因此间隔类似于
- -5 至 -3.95
- -4.05 至 -2.95
- ...
- -2.05 至 -0.95
- -1.05 到 0 而不是 -1.05 到 0.05
- 0 到 1.05 而不是 -0.05 到 1.05
- 0.95 到 2.05
- ...
有没有办法在 R 中实现这一点?
编辑:df
df
看起来像这样:
other_var ... x1 ... another_var ...
100 ... 4 ... 18 ...
12.3 ... 3.84 ... -6.2 ...
1.4 ... 4.78 ... 4.78 ...
-2 ... -2.51 ... 7.1 ...
-3.2 ... 0.57 ... -1 ...
dput(df1)
structure(list(x0 = c(0.702166747375488, 0.205532096598193, 0.0704982518296982,
-0.159150628995597, -0.162625494967927, -0.331660025490033, -0.099135847436449,
-0.137985446193678, -0.179304942878067, 0.0554309512268647),
x1 = c(-0.561621170364712, -0.762747775318984, 1.63791710226613,
-0.861210697757564, -1.05393723031543, 0.809872536189693,
2.85973319518198, 0.211750306033687, 1.18360826959114, -0.358159130198865
), x2 = c(-0.304711385106637, 0.365667729645747, -0.406328268107825,
-0.315315872233279, -0.477546612710489, 0.251158976293131,
-1.1263800774781, 0.229002212764429, -0.00413111289214729,
-0.252467704090853)), .Names = c("x0", "x1", "x2"), row.names = c(NA,
10L), class = "data.frame")
我看不到使用不会导致多列的切割创建间隔的解决方案,所以我从另一个角度接近它:遍历所有切割点和 return 该最小值和最大值的子集。
intervals <- data.frame(min=c(-5,-4.05+0:3,0,0.95+0:3))
intervals$max <- rev(intervals$min)*-1
intervals$name <- with(intervals, sprintf("[%.2f;%.2f)",min,max))
res <- lapply(split(intervals,intervals$name), function(x){
return(df1[df1$x1> x$min & df1$x1 <= x$max,])
})
> head(res)
$`[-1.05;-0.00)`
x0 x1 x2
1 0.70216675 -0.5616212 -0.3047114
2 0.20553210 -0.7627478 0.3656677
4 -0.15915063 -0.8612107 -0.3153159
10 0.05543095 -0.3581591 -0.2524677
$`[-2.05;-0.95)`
x0 x1 x2
5 -0.1626255 -1.053937 -0.4775466
$`[-3.05;-1.95)`
[1] x0 x1 x2
<0 rows> (or 0-length row.names)
$`[-4.05;-2.95)`
[1] x0 x1 x2
<0 rows> (or 0-length row.names)
$`[-5.00;-3.95)`
[1] x0 x1 x2
<0 rows> (or 0-length row.names)
$`[0.00;1.05)`
x0 x1 x2
6 -0.3316600 0.8098725 0.2511590
8 -0.1379854 0.2117503 0.2290022
这是一个使用 data.table 包中的 foverlaps(...)
的解决方案。很遗憾。你需要最新的开发版本才能工作。使用其他答案中的 intervals
data.frame。
##install.packages("devtools")
# library(devtools)
# install_github("Rdatatable/data.table", build_vignettes = FALSE)
library(data.table)
y <- with(df1,data.table(row=1:nrow(df1),lo=x1, hi=x1, key=c("lo","hi")))
cuts <- foverlaps(setDT(intervals),y, by.x=c("min","max"))[,list(row,name)]
lapply(split(cuts, cuts$name),function(s)df1[sort(s$row),])
# $`[-1.05;-0.00)`
# x0 x1 x2
# 1 0.70216675 -0.5616212 -0.3047114
# 2 0.20553210 -0.7627478 0.3656677
# 4 -0.15915063 -0.8612107 -0.3153159
# 10 0.05543095 -0.3581591 -0.2524677
#
# $`[-2.05;-0.95)`
# x0 x1 x2
# 5 -0.1626255 -1.053937 -0.4775466
#
# $`[-3.05;-1.95)`
# [1] x0 x1 x2
# <0 rows> (or 0-length row.names)
#...
foverlaps(x,y,...)
执行 "overlap join",即它找到 y
中与 x
中重叠的所有记录。重叠被定义为 y
中的列之间的范围内的值(例如,a 和 b),它们与 x
中的两列(例如 c 和 d)中的相应范围重叠。在这种情况下我们使用,对于x
,intervals
data.frame(转换为data.table),对于y
,形成data.table lo 和 hi 列都 = df$x1
.
我有一个数据框 df
,其中有一列名为 x1
,其值介于 -5 和 +5 之间。我试图为 df
的每一行分配一个关于 x1
值的间隔。函数 cut
允许我这样做 :
cut(df$x1,c(-5,-4,-3,-2,-1,0,1,2,3,4,5))
然后我可以使用 by
将 df
拆分为 10 data.frames
。不幸的是,我想要分配间隔,例如 -5 到 -3.95、-4.05 到 -2.95、-3.05 到 -1.95 等等,这意味着:
- 4.06将在区间3.95-5.05
- 4.05将在区间3.95-5.05和2.95-4.05
- 4.04将在区间3.95-5.05和2.95-4.05
- 3.94将在区间2.95-4.05
这意味着在使用 by
之后,我将有 10 个数据帧,其中 2 个数据帧中有一些元素。
我的问题的下一部分将涉及 0 附近的值:间隔不应包含负值和正值,因此间隔类似于
- -5 至 -3.95
- -4.05 至 -2.95
- ...
- -2.05 至 -0.95
- -1.05 到 0 而不是 -1.05 到 0.05
- 0 到 1.05 而不是 -0.05 到 1.05
- 0.95 到 2.05
- ...
有没有办法在 R 中实现这一点?
编辑:df
df
看起来像这样:
other_var ... x1 ... another_var ...
100 ... 4 ... 18 ...
12.3 ... 3.84 ... -6.2 ...
1.4 ... 4.78 ... 4.78 ...
-2 ... -2.51 ... 7.1 ...
-3.2 ... 0.57 ... -1 ...
dput(df1)
structure(list(x0 = c(0.702166747375488, 0.205532096598193, 0.0704982518296982,
-0.159150628995597, -0.162625494967927, -0.331660025490033, -0.099135847436449,
-0.137985446193678, -0.179304942878067, 0.0554309512268647),
x1 = c(-0.561621170364712, -0.762747775318984, 1.63791710226613,
-0.861210697757564, -1.05393723031543, 0.809872536189693,
2.85973319518198, 0.211750306033687, 1.18360826959114, -0.358159130198865
), x2 = c(-0.304711385106637, 0.365667729645747, -0.406328268107825,
-0.315315872233279, -0.477546612710489, 0.251158976293131,
-1.1263800774781, 0.229002212764429, -0.00413111289214729,
-0.252467704090853)), .Names = c("x0", "x1", "x2"), row.names = c(NA,
10L), class = "data.frame")
我看不到使用不会导致多列的切割创建间隔的解决方案,所以我从另一个角度接近它:遍历所有切割点和 return 该最小值和最大值的子集。
intervals <- data.frame(min=c(-5,-4.05+0:3,0,0.95+0:3))
intervals$max <- rev(intervals$min)*-1
intervals$name <- with(intervals, sprintf("[%.2f;%.2f)",min,max))
res <- lapply(split(intervals,intervals$name), function(x){
return(df1[df1$x1> x$min & df1$x1 <= x$max,])
})
> head(res)
$`[-1.05;-0.00)`
x0 x1 x2
1 0.70216675 -0.5616212 -0.3047114
2 0.20553210 -0.7627478 0.3656677
4 -0.15915063 -0.8612107 -0.3153159
10 0.05543095 -0.3581591 -0.2524677
$`[-2.05;-0.95)`
x0 x1 x2
5 -0.1626255 -1.053937 -0.4775466
$`[-3.05;-1.95)`
[1] x0 x1 x2
<0 rows> (or 0-length row.names)
$`[-4.05;-2.95)`
[1] x0 x1 x2
<0 rows> (or 0-length row.names)
$`[-5.00;-3.95)`
[1] x0 x1 x2
<0 rows> (or 0-length row.names)
$`[0.00;1.05)`
x0 x1 x2
6 -0.3316600 0.8098725 0.2511590
8 -0.1379854 0.2117503 0.2290022
这是一个使用 data.table 包中的 foverlaps(...)
的解决方案。很遗憾。你需要最新的开发版本才能工作。使用其他答案中的 intervals
data.frame。
##install.packages("devtools")
# library(devtools)
# install_github("Rdatatable/data.table", build_vignettes = FALSE)
library(data.table)
y <- with(df1,data.table(row=1:nrow(df1),lo=x1, hi=x1, key=c("lo","hi")))
cuts <- foverlaps(setDT(intervals),y, by.x=c("min","max"))[,list(row,name)]
lapply(split(cuts, cuts$name),function(s)df1[sort(s$row),])
# $`[-1.05;-0.00)`
# x0 x1 x2
# 1 0.70216675 -0.5616212 -0.3047114
# 2 0.20553210 -0.7627478 0.3656677
# 4 -0.15915063 -0.8612107 -0.3153159
# 10 0.05543095 -0.3581591 -0.2524677
#
# $`[-2.05;-0.95)`
# x0 x1 x2
# 5 -0.1626255 -1.053937 -0.4775466
#
# $`[-3.05;-1.95)`
# [1] x0 x1 x2
# <0 rows> (or 0-length row.names)
#...
foverlaps(x,y,...)
执行 "overlap join",即它找到 y
中与 x
中重叠的所有记录。重叠被定义为 y
中的列之间的范围内的值(例如,a 和 b),它们与 x
中的两列(例如 c 和 d)中的相应范围重叠。在这种情况下我们使用,对于x
,intervals
data.frame(转换为data.table),对于y
,形成data.table lo 和 hi 列都 = df$x1
.