首先,您的数据:
df1 <- read.table(text = "subject x y
7G001-0024-10 0,00 15
7G001-0024-10 97,29 18
7G001-0024-10 197,34 21
7G001-0024-10 314,66 22
7G001-0024-10 482,77 25
7G001-0030-10 0,00 12
7G001-0030-10 99,50 16
7G001-0030-10 184,37 20
7G001-0030-10 301,89 25
7G001-0030-10 585,67 27", header = TRUE, dec = ",")
df2 <- read.table(text = "subject Threshold
7G001-0024-10 177,08
7G001-0030-10 385,13", header = TRUE, dec = ",")
您可以使用简单apply
的方法来解决任务:
do.call("rbind", apply(df2, 1, FUN = function(a) {df1[a[1] == df1$subject & df1$x >= 0 & df1$x <= as.numeric(a[2]), ]}))
# subject x y
# 1 7G001-0024-10 0.00 15
# 2 7G001-0024-10 97.29 18
# 6 7G001-0030-10 0.00 12
# 7 7G001-0030-10 99.50 16
# 8 7G001-0030-10 184.37 20
# 9 7G001-0030-10 301.89 25
它是如何工作的?
首先,该函数apply(df2, 1, FUN)
将一个函数应用于数据框中的每一行df2
。该值1
表示该函数应用于对象的第一个维度(第二个维度是列)。
看一个简单的函数。它只返回第一行和第二行df2
。请注意,在输出中,行排列为列。
> apply(df2, 1, FUN = function(a) a)
[,1] [,2]
subject "7G001-0024-10" "7G001-0030-10"
Threshold "177.08" "385.13"
因为我们要提取一个df1
更复杂函数的子集,所以需要。所以,我指定:
FUN = function(a) {df1[a[1] == df1$subject & df1$x >= 0 & df1$x <= as.numeric(a[2]), ]}
在这个函数中,a
代表一行数据框df2
。此函数应用了两次,一次用于 的两行df2
。a[1]
是主题编号,a[2]
是对应的阈值。df1
该函数通过三个标准提取数据帧的行子集:
- 主题相同 (
a[1] == df1$subject
)
- 该
x
值至少为零 ( df1$x >= 0
)
- 该
x
值不高于阈值 ( df1$x <=
as.numeric(a[2])
)
注意:该值a[2]
需要通过 转换为数字as.numeric
。这是必要的,因为主题 id indf2
表示为字符,从而apply
将整行(包括阈值)转换为字符。
这些条件中的每一个都返回一个逻辑向量。这些向量被组合&
成一个逻辑向量,指示是否所有三个标准都被满足。选择逻辑向量所在的df1[logical.vector, ]
所有行。由于 之后没有指定任何内容,因此选择了所有列。df1
TRUE
,
df1
函数返回所有三个条件都已完成的行apply
。
> apply(df2, 1, FUN = function(a) {df1[a[1] == df1$subject & df1$x >= 0 & df1$x <= as.numeric(a[2]), ]})
[[1]]
subject x y
1 7G001-0024-10 0.00 15
2 7G001-0024-10 97.29 18
[[2]]
subject x y
6 7G001-0030-10 0.00 12
7 7G001-0030-10 99.50 16
8 7G001-0030-10 184.37 20
9 7G001-0030-10 301.89 25
该函数apply
返回两个数据框的列表,每行一个df2
。
最后一步,将列表中的数据框合并为一个数据框。该函数do.call("rbind", list)
执行该函数rbind
并将列表中的参数传递给它。对于长度为 2 的列表,这相当于rbind(list[[1]], list[[2]])
. 这样,返回的列表中的两个数据帧就apply
被合并了。