在列表上递归应用函数
Applying a function recursively over a list
我正在尝试使用 lapply 和包含多个 for 循环的手工函数将向量的值应用于字符向量列表。啊!基本上我所拥有的是一个字符向量列表,看起来像这样 (filename_lists3
):
$`809`
[1] "rakelib/blueprint.rb" "projects/daedalus/daedalus.rb"
$`859`
[1] "README"
...
和一个命名的数字向量,如下所示 (degree_list
):
projects/daedalus/daedalus.rb rakelib/blueprint.rb
1 5
README README.mdown
6 1
...
我要做的是将filename_list3
中的字符串与names(degree_list)
中的字符串进行匹配,当它们相同时,将filename_list3
中的字符串替换为degree_list
.
中的整数
这是我的代码:
dput(filename_lists3[1:10])
structure(list(`809` = c("rakelib/blueprint.rb", "projects/daedalus/daedalus.rb"
), `859` = "README", `957` = "spec/debugger/spec_helper.rb",
`1007` = c("README.mdown", "README"), `1038` = "spec/ruby/core/file/stat/setgid_spec.rb",
`1099` = c("vm/test/test_embedding.hpp", "vm/embed.c", "vm/api/embed.h"
), `1179` = c("vm/capi/module.cpp", "kernel/common/module19.rb",
"kernel/common/module18.rb"), `1235` = c("vm/builtin/thread.hpp",
"vm/builtin/thread.cpp", "kernel/common/thread.rb", "kernel/bootstrap/thread.rb"
), `1390` = "spec/ruby/core/marshal/dump_spec.rb", `1422` = c("spec/tags/19/ruby/core/module/constants_tags.txt",
"kernel/common/module19.rb", "kernel/common/module18.rb",
"kernel/common/module.rb")), .Names = c("809", "859", "957",
"1007", "1038", "1099", "1179", "1235", "1390", "1422"))
dput(degree_list[1:10])
structure(c(1, 5, 6, 1, 2, 2, 2, 5, 7, 2), .Names = c("projects/daedalus/daedalus.rb",
"rakelib/blueprint.rb", "README", "README.mdown", "vm/api/embed.h",
"vm/embed.c", "vm/test/test_embedding.hpp", "kernel/common/module18.rb",
"kernel/common/module19.rb", "vm/capi/module.cpp"))
以及函数和 lapply 调用:
insert_sna_stat <- function(x, input = degree_list){
for (i in 1:length(x)){
for (n in 1:length(input))
if (names(input)[n] == x[i])
x[i] <- input[n] else
x[i] <- x[i]
}
}
lapply(filename_lists3, insert_sna_stat)
此时只生成空值。这里出了什么问题?我怎样才能修改它以执行我上面描述的操作?
您可以使用 rapply
:
> rapply(filename_lists3, function(x) ifelse(x %in% names(degree_list), degree_list[x], x), how='replace')
$`809`
[1] 5 1
$`859`
[1] 6
$`957`
[1] "spec/debugger/spec_helper.rb"
$`1007`
[1] 1 6
$`1038`
[1] "spec/ruby/core/file/stat/setgid_spec.rb"
$`1099`
[1] 2 2 2
$`1179`
[1] 2 7 5
$`1235`
[1] "vm/builtin/thread.hpp" "vm/builtin/thread.cpp"
[3] "kernel/common/thread.rb" "kernel/bootstrap/thread.rb"
$`1390`
[1] "spec/ruby/core/marshal/dump_spec.rb"
$`1422`
[1] "spec/tags/19/ruby/core/module/constants_tags.txt"
[2] "7"
[3] "5"
[4] "kernel/common/module.rb"
您可以 lapply
遍历您的文件名列表并使用这些值来对学位列表进行子集化。如果没有匹配项,您将获得 NA,因此在这种情况下将 ifelse
环绕并 return 原始值。
lapply(filename_lists3, function(x) ifelse(is.na(degree_list[x]),x,degree_list[x]))
$`809`
rakelib/blueprint.rb projects/daedalus/daedalus.rb
5 1
$`859`
README
6
$`957`
<NA>
"spec/debugger/spec_helper.rb"
$`1007`
README.mdown README
1 6
$`1038`
<NA>
"spec/ruby/core/file/stat/setgid_spec.rb"
$`1099`
vm/test/test_embedding.hpp vm/embed.c
2 2
vm/api/embed.h
2
$`1179`
vm/capi/module.cpp kernel/common/module19.rb kernel/common/module18.rb
2 7 5
$`1235`
<NA> <NA>
"vm/builtin/thread.hpp" "vm/builtin/thread.cpp"
<NA> <NA>
"kernel/common/thread.rb" "kernel/bootstrap/thread.rb"
$`1390`
<NA>
"spec/ruby/core/marshal/dump_spec.rb"
$`1422`
<NA>
"spec/tags/19/ruby/core/module/constants_tags.txt"
kernel/common/module19.rb
"7"
kernel/common/module18.rb
"5"
<NA>
"kernel/common/module.rb"
您可以使用match
函数:
res <- lapply(filename_lists3, function(x){
m <- match(x,names(degree_list))
x[!is.na(m)] <- degree_list[m[!is.na(m)]]
return(x)
})
##### results
> res
$`809`
[1] "5" "1"
$`859`
[1] "6"
$`957`
[1] "spec/debugger/spec_helper.rb"
$`1007`
[1] "1" "6"
$`1038`
[1] "spec/ruby/core/file/stat/setgid_spec.rb"
$`1099`
[1] "2" "2" "2"
$`1179`
[1] "2" "7" "5"
$`1235`
[1] "vm/builtin/thread.hpp" "vm/builtin/thread.cpp" "kernel/common/thread.rb" "kernel/bootstrap/thread.rb"
$`1390`
[1] "spec/ruby/core/marshal/dump_spec.rb"
$`1422`
[1] "spec/tags/19/ruby/core/module/constants_tags.txt" "7"
[3] "5" "kernel/common/module.rb"
我觉得你最好在这里使用merge
。但是,首先您应该将列表转换为 data.frames.
D1 <- do.call(rbind,lapply(seq_along(filename_lists),
function(i) data.frame(name=filename_lists[[i]],
id = names(filename_lists)[i])))
D2 <- as.data.frame(degree_list)
D2$name <- rownames(D2)
merge(D1,D2,all.x=TRUE)
# name id degree_list
# 1 projects/daedalus/daedalus.rb 809 1
# 2 rakelib/blueprint.rb 809 5
# 3 README 859 6
# 4 README 1007 6
# 5 spec/debugger/spec_helper.rb 957 NA
# 6 README.mdown 1007 1
# 7 spec/ruby/core/file/stat/setgid_spec.rb 1038 NA
# 8 vm/api/embed.h 1099 2
# 9 vm/embed.c 1099 2
# 10 vm/test/test_embedding.hpp 1099 2
# 11 kernel/common/module18.rb 1179 5
# 12 kernel/common/module18.rb 1422 5
# 13 kernel/common/module19.rb 1179 7
# 14 kernel/common/module19.rb 1422 7
# 15 vm/capi/module.cpp 1179 2
# 16 kernel/bootstrap/thread.rb 1235 NA
# 17 kernel/common/thread.rb 1235 NA
# 18 vm/builtin/thread.cpp 1235 NA
# 19 vm/builtin/thread.hpp 1235 NA
# 20 spec/ruby/core/marshal/dump_spec.rb 1390 NA
# 21 kernel/common/module.rb 1422 NA
# 22 spec/tags/19/ruby/core/module/constants_tags.txt 1422 NA
我正在尝试使用 lapply 和包含多个 for 循环的手工函数将向量的值应用于字符向量列表。啊!基本上我所拥有的是一个字符向量列表,看起来像这样 (filename_lists3
):
$`809`
[1] "rakelib/blueprint.rb" "projects/daedalus/daedalus.rb"
$`859`
[1] "README"
...
和一个命名的数字向量,如下所示 (degree_list
):
projects/daedalus/daedalus.rb rakelib/blueprint.rb
1 5
README README.mdown
6 1
...
我要做的是将filename_list3
中的字符串与names(degree_list)
中的字符串进行匹配,当它们相同时,将filename_list3
中的字符串替换为degree_list
.
这是我的代码:
dput(filename_lists3[1:10])
structure(list(`809` = c("rakelib/blueprint.rb", "projects/daedalus/daedalus.rb"
), `859` = "README", `957` = "spec/debugger/spec_helper.rb",
`1007` = c("README.mdown", "README"), `1038` = "spec/ruby/core/file/stat/setgid_spec.rb",
`1099` = c("vm/test/test_embedding.hpp", "vm/embed.c", "vm/api/embed.h"
), `1179` = c("vm/capi/module.cpp", "kernel/common/module19.rb",
"kernel/common/module18.rb"), `1235` = c("vm/builtin/thread.hpp",
"vm/builtin/thread.cpp", "kernel/common/thread.rb", "kernel/bootstrap/thread.rb"
), `1390` = "spec/ruby/core/marshal/dump_spec.rb", `1422` = c("spec/tags/19/ruby/core/module/constants_tags.txt",
"kernel/common/module19.rb", "kernel/common/module18.rb",
"kernel/common/module.rb")), .Names = c("809", "859", "957",
"1007", "1038", "1099", "1179", "1235", "1390", "1422"))
dput(degree_list[1:10])
structure(c(1, 5, 6, 1, 2, 2, 2, 5, 7, 2), .Names = c("projects/daedalus/daedalus.rb",
"rakelib/blueprint.rb", "README", "README.mdown", "vm/api/embed.h",
"vm/embed.c", "vm/test/test_embedding.hpp", "kernel/common/module18.rb",
"kernel/common/module19.rb", "vm/capi/module.cpp"))
以及函数和 lapply 调用:
insert_sna_stat <- function(x, input = degree_list){
for (i in 1:length(x)){
for (n in 1:length(input))
if (names(input)[n] == x[i])
x[i] <- input[n] else
x[i] <- x[i]
}
}
lapply(filename_lists3, insert_sna_stat)
此时只生成空值。这里出了什么问题?我怎样才能修改它以执行我上面描述的操作?
您可以使用 rapply
:
> rapply(filename_lists3, function(x) ifelse(x %in% names(degree_list), degree_list[x], x), how='replace')
$`809`
[1] 5 1
$`859`
[1] 6
$`957`
[1] "spec/debugger/spec_helper.rb"
$`1007`
[1] 1 6
$`1038`
[1] "spec/ruby/core/file/stat/setgid_spec.rb"
$`1099`
[1] 2 2 2
$`1179`
[1] 2 7 5
$`1235`
[1] "vm/builtin/thread.hpp" "vm/builtin/thread.cpp"
[3] "kernel/common/thread.rb" "kernel/bootstrap/thread.rb"
$`1390`
[1] "spec/ruby/core/marshal/dump_spec.rb"
$`1422`
[1] "spec/tags/19/ruby/core/module/constants_tags.txt"
[2] "7"
[3] "5"
[4] "kernel/common/module.rb"
您可以 lapply
遍历您的文件名列表并使用这些值来对学位列表进行子集化。如果没有匹配项,您将获得 NA,因此在这种情况下将 ifelse
环绕并 return 原始值。
lapply(filename_lists3, function(x) ifelse(is.na(degree_list[x]),x,degree_list[x]))
$`809`
rakelib/blueprint.rb projects/daedalus/daedalus.rb
5 1
$`859`
README
6
$`957`
<NA>
"spec/debugger/spec_helper.rb"
$`1007`
README.mdown README
1 6
$`1038`
<NA>
"spec/ruby/core/file/stat/setgid_spec.rb"
$`1099`
vm/test/test_embedding.hpp vm/embed.c
2 2
vm/api/embed.h
2
$`1179`
vm/capi/module.cpp kernel/common/module19.rb kernel/common/module18.rb
2 7 5
$`1235`
<NA> <NA>
"vm/builtin/thread.hpp" "vm/builtin/thread.cpp"
<NA> <NA>
"kernel/common/thread.rb" "kernel/bootstrap/thread.rb"
$`1390`
<NA>
"spec/ruby/core/marshal/dump_spec.rb"
$`1422`
<NA>
"spec/tags/19/ruby/core/module/constants_tags.txt"
kernel/common/module19.rb
"7"
kernel/common/module18.rb
"5"
<NA>
"kernel/common/module.rb"
您可以使用match
函数:
res <- lapply(filename_lists3, function(x){
m <- match(x,names(degree_list))
x[!is.na(m)] <- degree_list[m[!is.na(m)]]
return(x)
})
##### results
> res
$`809`
[1] "5" "1"
$`859`
[1] "6"
$`957`
[1] "spec/debugger/spec_helper.rb"
$`1007`
[1] "1" "6"
$`1038`
[1] "spec/ruby/core/file/stat/setgid_spec.rb"
$`1099`
[1] "2" "2" "2"
$`1179`
[1] "2" "7" "5"
$`1235`
[1] "vm/builtin/thread.hpp" "vm/builtin/thread.cpp" "kernel/common/thread.rb" "kernel/bootstrap/thread.rb"
$`1390`
[1] "spec/ruby/core/marshal/dump_spec.rb"
$`1422`
[1] "spec/tags/19/ruby/core/module/constants_tags.txt" "7"
[3] "5" "kernel/common/module.rb"
我觉得你最好在这里使用merge
。但是,首先您应该将列表转换为 data.frames.
D1 <- do.call(rbind,lapply(seq_along(filename_lists),
function(i) data.frame(name=filename_lists[[i]],
id = names(filename_lists)[i])))
D2 <- as.data.frame(degree_list)
D2$name <- rownames(D2)
merge(D1,D2,all.x=TRUE)
# name id degree_list
# 1 projects/daedalus/daedalus.rb 809 1
# 2 rakelib/blueprint.rb 809 5
# 3 README 859 6
# 4 README 1007 6
# 5 spec/debugger/spec_helper.rb 957 NA
# 6 README.mdown 1007 1
# 7 spec/ruby/core/file/stat/setgid_spec.rb 1038 NA
# 8 vm/api/embed.h 1099 2
# 9 vm/embed.c 1099 2
# 10 vm/test/test_embedding.hpp 1099 2
# 11 kernel/common/module18.rb 1179 5
# 12 kernel/common/module18.rb 1422 5
# 13 kernel/common/module19.rb 1179 7
# 14 kernel/common/module19.rb 1422 7
# 15 vm/capi/module.cpp 1179 2
# 16 kernel/bootstrap/thread.rb 1235 NA
# 17 kernel/common/thread.rb 1235 NA
# 18 vm/builtin/thread.cpp 1235 NA
# 19 vm/builtin/thread.hpp 1235 NA
# 20 spec/ruby/core/marshal/dump_spec.rb 1390 NA
# 21 kernel/common/module.rb 1422 NA
# 22 spec/tags/19/ruby/core/module/constants_tags.txt 1422 NA