【问题标题】:How to convert this nested for loop into a purrr function如何将此嵌套的 for 循环转换为 purrr 函数
【发布时间】:2021-03-16 17:28:17
【问题描述】:

好的,我正在尝试使用一些 purrr 映射函数替换嵌套 for 循环与另一个 for 循环配对的使用,但我只是找不到它。我所拥有的是数据框列表,我知道每个数据框中至少有一列包含与不在列表中的另一个数据框中的数据匹配。我需要的是找到列表中包含的数据框中的列,这些列包含与外部数据框中的值匹配的值,并重命名列表中包含的数据框中的这些列。

需要明确的是,数据帧都是不同数量的行,我在 dfs 列表中查找的数据和我正在检查的数据帧是数十万个随机字符串值 - 它不是就像我下面的例子看起来很简单,但这个例子描绘了画面。

这是我的数据的播放版本。

library(dplyr)
x <- data.frame(first = c(1:3, 6:7),
                second = c(1:3, 6:7),
                third = c(1:5))

y <- data.frame(differ = c(10:13),
                other = c(10:13),
                nomatch = rep(5),
                another = c(10:13),
                argh = c(9:12))

z <- data.frame(nothing = c(20:27),
                nope = c(20:27),
                noway = c(16,17, 18, 19, 5, 21, 22, 23),
                still = c(21:28),
                again = c(22:29))

frame_list <- list(first = x, 
                   second = y, 
                   third = z)

check_against <- data.frame(checking = rep(5, times = 5))

col_name_list <- list()

for (i in 1:length(frame_list)) {
  for (j in 1:length(frame_list[[i]])) {
    if (sum(!(is.na(frame_list[[i]][[j]])) 
            & frame_list[[i]][[j]] 
            %in% check_against[[1]]) > 0) {
      col_name_list[[i]] <- names(frame_list[[i]][j])
    }
  }
}

for (i in 1:length(frame_list)) {
  frame_list[[i]] <- rename(frame_list[[i]],
                            I_want_this_one = col_name_list[[i]])
}

这得到了我想要的,但我很想用 purrr 或应用函数替换它。

我尝试了一些根本没有任何帮助的方法:

library(purrr)

map(frame_list, names) %>% 
  imap(., unlist(.), function(x, y) {if (sum(!(is.na(x[[y]])) 
                           & x[[y]] 
                           %in% check_against[[1]]) > 0) {
    col_name_list[[y]] <- names(x[[y]])
    
  }
    x[[y]] <- rename(x[[y]],
                    I_want_this_one = col_name_list[[y]])
    })

# or this
map(frame_list, unlist) %>% 
  imap(., names(.), function(x, y) {if (sum(!(is.na(x[[y]])) 
                                             & x[[y]] 
                                             %in% check_against[[1]]) > 0) {
    col_name_list[[y]] <- names(x[[y]])
    
  }
    x[[y]] <- rename(x[[y]],
                     I_want_this_one = col_name_list[[y]])
  })

我很难用一种实用的方法来实现这一点。

非常感谢任何建议!

【问题讨论】:

    标签: r for-loop purrr nested-for-loop


    【解决方案1】:

    对于第一个 purrr 调用,给出 frame_list,对于第二个,给出数据表的名称。我在数据框 y 中添加了一个 blah 列,也发生了变化

    library(dplyr)
    x <- data.frame(first = c(1:3, 6:7),
                    second = c(1:3, 6:7),
                    third = c(1:5))
    
    y <- data.frame(differ = c(10:13),
                    other = c(10:13),
                    nomatch = rep(5),
                    blah=rep(5),
                    another = c(10:13),
                    argh = c(9:12))
    
    z <- data.frame(nothing = c(20:27),
                    nope = c(20:27),
                    noway = c(16,17, 18, 19, 5, 21, 22, 23),
                    still = c(21:28),
                    again = c(22:29))
    
    frame_list <- list(first = x, 
                       second = y, 
                       third = z)
    
    check_against <- rep(5, 5)
    
    col_name_list=purrr::map(frame_list, function(w) {
      m=purrr::map_lgl(w, function(x) {
        return(any(unlist(x) %in% check_against))
      })
      names(w)[m]
    })
    
    col_name_list
    

    输出

    $first
    [1] "third"
    
    $second
    [1] "nomatch" "blah"   
    
    $third
    [1] "noway"
    

    【讨论】:

    • 这发送到了正确的方向 - 让我走了大约 90% 的路。我还想更改数据框中列的名称。我最终使用了你在这里所拥有的变体,使用purrr::detect_index 而不是map_lgl 并在两个函数之后通过管道连接到map2 来分配列名。这是一个巨大的帮助,它让我进入了正确的思维框架来思考这些 purrr 函数是如何工作的。谢谢!
    猜你喜欢
    • 2021-09-16
    • 2013-01-04
    • 2020-10-01
    • 1970-01-01
    • 2023-04-01
    • 2020-11-26
    • 1970-01-01
    • 2012-11-06
    • 1970-01-01
    相关资源
    最近更新 更多