在列表上递归应用函数

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