我有一个数据框:
df = read.table(text="ID location C1 C2 C3 C4 C5 C6
M01 1 A H H A A B
M02 2 A H A A A B
M03 3 A B A A A B
M04 4 H B H A A B
M05 5 H B H A A B
M06 6 A B H A A H
M07 7 A B H B A H
M08 8 A B H A A H
M09 9 A B H A A H
M10 10 B B H A A H
M11 11 A B H A A H
M12 12 A B H A A H
M13 13 A B H A A H
M14 14 B B B A A H
M15 15 B B B A A A", header=T, stringsAsFactors=F)
我想根据df$ID
的索引行号列表提取df
的值。列表a
是:
a = list(C1 = c(3, 5, 9, 10, 13), C2 = c(2) ,
C3 = c(1, 3, 13 ), C4 =c(6, 7 ), C6 = c(5, 14 ))
预期结果是:
$C1
[1] "M03" "M05" "M09" "M10" "M13"
$C2
[1] "M02"
$C3
[1] "M01" "M03" "M13"
$C4
[1] "M06" "M07"
$C6
[1] "M05" "M14"
答案 0 :(得分:7)
您可以取消列出a
列表,索引数据值,然后relist
将其自身作为骨架。
relist(df$ID[unlist(a)], a)
# $C1
# [1] "M03" "M05" "M09" "M10" "M13"
#
# $C2
# [1] "M02"
#
# $C3
# [1] "M01" "M03" "M13"
#
# $C4
# [1] "M06" "M07"
#
# $C6
# [1] "M05" "M14"
此外,如果我们删除unlist
中的名称,我们可以提高速度。
relist(df$ID[unlist(a, use.names = FALSE)], a)
注意:
另一个答案的基准是误导性的。这是更准确的基准测试,显示了另一个答案的实际代码,该答案在每次迭代时使用$
提取并删除表达式周围不必要的{}
括号... < / p>
df <- data.frame(v1 = paste0("M", 1:1e6))
set.seed(24)
a1 <- lapply(1:1e4, function(i) sample(1:1e6, sample(1e3), replace=FALSE))
system.time(relist(df$v1[unlist(a1, use.names = FALSE)], a1))
# user system elapsed
# 0.485 0.004 0.489
system.time(lapply(a1, function(x) df$v1[x]))
# user system elapsed
# 0.39 0.00 0.39
答案 1 :(得分:3)
这可以通过循环lapply
并{0}提取list
来轻松完成。基于每个list
元素
lapply(a, function(x) df$ID[x])
#$C1
#[1] "M03" "M05" "M09" "M10" "M13"
#$C2
#[1] "M02"
#$C3
#[1] "M01" "M03" "M13"
#$C4
#[1] "M06" "M07"
#$C6
#[1] "M05" "M14"
或者我们可以使用Map
的紧凑选项来完成工作
Map(`[`, list(df$ID), a)
#[[1]]
#[1] "M03" "M05" "M09" "M10" "M13"
#[[2]]
#[1] "M02"
#[[3]]
#[1] "M01" "M03" "M13"
#[[4]]
#[1] "M06" "M07"
#[[5]]
#[1] "M05" "M14"
nchar("Map(`[`, list(df$ID), a)")
#[1] 24
此处,基准测试基于vector
(&#39; v1&#39;)和list
(&#39; a1&#39;)。
v1 <- paste0("M", 1:1e6)
如果是data.frame
列(v1 <- someDat$ID
),以避免重复提取。
set.seed(24)
a1 <- lapply(1:1e4, function(i) sample(1:1e6, sample(1e3), replace=FALSE))
system.time(relist(v1[unlist(a1, use.names = FALSE)], a1))
# user system elapsed
# 0.81 0.03 0.84
system.time(lapply(a1, function(x) v1[x]))
# user system elapsed
# 0.36 0.00 0.36
system.time(Map(`[`, list(v1), a1))
# user system elapsed
# 0.35 0.00 0.34
注意:删除了{}
(我们之前忽略了这一点),但基准测试中仍然没有太大变化。如前所述,最好创建一个矢量对象(v1 <- someDat$ID
)并使用它来检查基准,而不是每次都提取列。在这方面,该基准测试符合准确基准测试的目的。