首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在转到R中的下一行之前为每一行生成函数返回值?

如何在转到R中的下一行之前为每一行生成函数返回值?
EN

Stack Overflow用户
提问于 2020-01-01 23:39:01
回答 2查看 149关注 0票数 4

我有以下数据框架:

代码语言:javascript
复制
lineups <- tibble::tribble(
                                                               ~lineupBefore,          ~playerOut,           ~playerIn,
  "Justise Winslow, Bam Adebayo, Meyers Leonard, Tyler Herro, Kendrick Nunn",     "Kendrick Nunn",      "Goran Dragic",
                                                                          NA,   "Justise Winslow", "Derrick Jones Jr.",
                                                                          NA,    "Meyers Leonard",      "Kelly Olynyk",
                                                                          NA,       "Bam Adebayo",   "Justise Winslow",
                                                                          NA,       "Tyler Herro",   "Duncan Robinson",
                                                                          NA, "Derrick Jones Jr.",       "Bam Adebayo",
                                                                          NA,      "Goran Dragic",     "Kendrick Nunn",
                                                                          NA,   "Justise Winslow",       "Tyler Herro",
                                                                          NA,      "Kelly Olynyk",    "Meyers Leonard",
                                                                          NA,       "Bam Adebayo",   "Justise Winslow"
  )

然后,我用以下内容创建了一个列:

代码语言:javascript
复制
lineups %>%
 mutate(lineupAfter = str_replace(lineupBefore, playerOut, playerIn))

其结果是:

代码语言:javascript
复制
tibble::tribble(
                                                                 ~lineupBefore,          ~playerOut,           ~playerIn,                                                              ~lineupAfter,
    "Justise Winslow, Bam Adebayo, Meyers Leonard, Tyler Herro, Kendrick Nunn",     "Kendrick Nunn",      "Goran Dragic", "Justise Winslow, Bam Adebayo, Meyers Leonard, Tyler Herro, Goran Dragic",
                                                                            NA,   "Justise Winslow", "Derrick Jones Jr.",                                                                        NA,
                                                                            NA,    "Meyers Leonard",      "Kelly Olynyk",                                                                        NA,
                                                                            NA,       "Bam Adebayo",   "Justise Winslow",                                                                        NA,
                                                                            NA,       "Tyler Herro",   "Duncan Robinson",                                                                        NA,
                                                                            NA, "Derrick Jones Jr.",       "Bam Adebayo",                                                                        NA,
                                                                            NA,      "Goran Dragic",     "Kendrick Nunn",                                                                        NA,
                                                                            NA,   "Justise Winslow",       "Tyler Herro",                                                                        NA,
                                                                            NA,      "Kelly Olynyk",    "Meyers Leonard",                                                                        NA,
                                                                            NA,       "Bam Adebayo",   "Justise Winslow",                                                                        NA
    )

现在,我希望lineupBefore中的NA值是来自lineupAfter的前一个值。然后,必须将创建lineupAfter列的相同函数应用于来自lineupBefore的新值。如果我尝试使用变体来实现它,它将只替换第一个NA行中的值。因此,在进入下一行之前,我需要该函数在每一行上工作,将其转换为与NA不同的内容。我想我需要用purrr来做这件事,但我不知道怎么做。任何帮助都将不胜感激!

编辑:

这是预期的前5行的样子:

代码语言:javascript
复制
tibble::tribble(
                                                                  ~lineupBefore,        ~playerOut,           ~playerIn,                                                                      ~lineupAfter,
     "Justise Winslow, Bam Adebayo, Meyers Leonard, Tyler Herro, Kendrick Nunn",   "Kendrick Nunn",      "Goran Dragic",         "Justise Winslow, Bam Adebayo, Meyers Leonard, Tyler Herro, Goran Dragic",
      "Justise Winslow, Bam Adebayo, Meyers Leonard, Tyler Herro, Goran Dragic", "Justise Winslow", "Derrick Jones Jr.",       "Derrick Jones Jr., Bam Adebayo, Meyers Leonard, Tyler Herro, Goran Dragic",
    "Derrick Jones Jr., Bam Adebayo, Meyers Leonard, Tyler Herro, Goran Dragic",  "Meyers Leonard",      "Kelly Olynyk",         "Derrick Jones Jr., Bam Adebayo, Kelly Olynyk, Tyler Herro, Goran Dragic",
      "Derrick Jones Jr., Bam Adebayo, Kelly Olynyk, Tyler Herro, Goran Dragic",     "Bam Adebayo",   "Justise Winslow",     "Derrick Jones Jr., Justise Winslow, Kelly Olynyk, Tyler Herro, Goran Dragic",
  "Derrick Jones Jr., Justise Winslow, Kelly Olynyk, Tyler Herro, Goran Dragic",     "Tyler Herro",   "Duncan Robinson", "Derrick Jones Jr., Justise Winslow, Kelly Olynyk, Duncan Robinson, Goran Dragic"
  )

如您所见,lineupBefore列的第2行将等于lineupAfter列的第1行,lineupBefore列的第3行将等于lineupAfter列的第2行,依此类推。同时,lineupAfter的第2行将是应用于lineupBefore的第2行的str_replace(lineupBefore、playerOut、playerIn)的结果,等等。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-01-02 02:11:23

您要求采用管道式{purrr}风格的方法。您在这里所做的是将更改从一组积累到另一组,因此您希望使用purrr::accumulatesetdiff

我认为让您的lineup*列列表更容易,而不是像它们那样的字符串。这意味着在列的每一行中存储一个名称向量,而不是在列中存储一个带有逗号的字符串。

从您的第一个lineups表开始:

代码语言:javascript
复制
library(stringr)
library(dplyr)
library(purrr)

lineups <- 
  tibble::tribble(
  ~lineupBefore,          ~playerOut,           ~playerIn,
  "Justise Winslow, Bam Adebayo, Meyers Leonard, Tyler Herro, Kendrick Nunn",     "Kendrick Nunn",      "Goran Dragic",
  NA,   "Justise Winslow", "Derrick Jones Jr.",
  NA,    "Meyers Leonard",      "Kelly Olynyk",
  NA,       "Bam Adebayo",   "Justise Winslow",
  NA,       "Tyler Herro",   "Duncan Robinson",
  NA, "Derrick Jones Jr.",       "Bam Adebayo",
  NA,      "Goran Dragic",     "Kendrick Nunn",
  NA,   "Justise Winslow",       "Tyler Herro",
  NA,      "Kelly Olynyk",    "Meyers Leonard",
  NA,       "Bam Adebayo",   "Justise Winslow"
)

lineups_list <- 
  lineups %>% 
  mutate(lineupBefore = str_split(lineupBefore, ", "))

lineups_list

A tibble: 10×3 lineupBefore playerOut playerIn 1 Kendrick Nunn Goran Dragic 2 Justise Derrick Jones Jr.3 梅耶斯伦纳德凯利奥利尼克4 巴姆阿德巴约贾斯蒂斯温斯洛5 泰勒赫罗邓肯罗宾逊6 德里克琼斯小。巴姆·阿德巴约7 Goran Goran Kendrick Nunn 8 Justise温斯洛·泰勒·赫罗9 凯利·奥利尼克·迈尔斯伦纳德10

现在您有了一个lineupBefore列,其中第一个元素是一个长度-5向量,所有的长度-1向量行都是单个NA值。

我们要做的函数是取第一个长度-5向量,然后依次将playerIn名称添加到向量中(c(initial_players, new_player)一次又一次)。如果我们有一场无限的篮球比赛,那就是我们所拥有的,只是不断地增加球员。purrr::accumulate将这样做,在每一步返回结果。

但是,我们也希望在每一步都能从playerOut中取出玩家。这和一遍又一遍的setdiff(current_players, removed_player)一样。为了同时做到这两点,我们使用了purrr::accumulate2

我们传递给它的函数依次在args ..1..2..3上操作,其中上一步的结果将成为下一步的..1。我们在playerIn中传递的第一个参数,也就是说每次都会向结果中添加..2。第二个参数是playerOut,这就是我们每次使用setdiff删除的..3。我们必须用首发名单(lineupBefore[[1]])来初始化它,否则它只会从一支没有球员的空队中积累起来。

您可以看到这样的输出:

代码语言:javascript
复制
x <- lineups_list$playerIn
y <- lineups_list$playerOut

accumulate2(
  x, y,  ~setdiff(c(..1, ..2), ..3), 
  .init = lineups_list$lineupBefore[[1]]
  )

[1]“公正的温斯洛”、“巴姆·阿德巴约”、“迈耶斯·伦纳德”、“泰勒·赫罗”、“肯德里克·努恩”[2]“正义·温斯洛”、“巴姆·阿德巴约”、“迈耶斯·伦纳德”、“泰勒·埃雷巴约”、“迈尔斯·莱纳德”、“戈兰·德巴巴约”[3]“贝姆·阿德巴约”、“迈耶斯·伦纳德”、“泰勒·赫罗”、“戈兰·德雷吉格”、“德里克·琼斯”[4]“贝姆·阿德巴约”“泰勒·埃罗”“戈兰·德拉吉”“德里克·琼斯”"Kelly Olynyk“[5] "Tyler”"Goran Dragic“"Derrick Jones Jr.”“凯利·奥利尼克”“正义·温斯洛”[6]“戈兰·德拉吉”“德里克·琼斯”"Kelly Olynyk“[8] "Kelly Olynyk”“J. Winslow”"Duncan Robinson“"Duncan Robinson”"Bam Adebayo“[9] "Kelly Olynyk”"Duncan Robinson“"Bam Adebayo”[8] "Kendrick Nunn“[10]“邓肯·鲁滨逊”“巴姆·阿德巴约”“肯德里克·努恩”“泰勒·赫罗”“迈尔斯·伦纳德”[11]“邓肯·鲁滨逊”“肯德里克·努恩”“泰勒·赫罗”“迈尔斯·伦纳德”“正义·温斯洛”

但是,这是一个长度为11的列表,这是因为我们从一个.init参数开始,因此它被算作步骤之一。然后,您可能会注意到,元素2-11是您希望用于lineupAfter的元素,而元素1-10是您希望用于lineupBefore的元素。因此,您可以使用相同的函数来计算这两个元素,只需要切断第一个元素或最后一个元素。(另外请注意,您只需使用lead/lag的某些版本来抵消一列与另一列的差异,这将使您无法计算这些函数两次。但我这样做是为了展示他们的平行结构。)

代码语言:javascript
复制
lineups_list_filled <- lineups_list %>% 
  mutate(
    lineupAfter = accumulate2(
      playerIn, playerOut, ~setdiff(c(..1, ..2), ..3),
      .init = lineupBefore[[1]]
    )[-1],                          # [] removes the head
    lineupBefore = accumulate2(
      playerIn, playerOut, ~setdiff(c(..1, ..2), ..3),
      .init = lineupBefore[[1]]
    )[-length(playerIn)]            # [] removes the last element
  )

lineups_list_filled

A tibble: 10×4 lineupBefore playerOut playerIn lineupAfter 1 Kendrick Nunn Goran Dragic 2 Justise Derrick Jr Jr. 3 Meyers Leonard Kelly 4 Bam Adebayo Winslow 5 Tyler Robinson 6 Derrick Jones Jr.Bam Adebayo 7 Goran Dragic Kendrick Nunn 8 Justise Tyler 9 Kelly Olynyk Meyers Leonard 10

如果您查看lineups_list_filled$lineupBeforelineups_list_filled$lineupAfter,您将看到它们匹配上面length-11列表的正确元素。例如,如果您想将它们折叠回字符串以进行打印,则始终可以执行以下操作:

代码语言:javascript
复制
lineups_list_filled %>% 
  mutate_all(
    ~map_chr(., ~paste(.x, collapse = ", "))
  )

只有当你有不重复的元素时,这个方法才能起作用,比如名册上的单个球员。例如,如果使用任意整数执行此操作,则不可能有3次,因为setdiff首先调用unique。在这种情况下,您可以构建自己的setdiff版本,使用matchwhich,并对边缘情况进行一些错误检查。

票数 2
EN

Stack Overflow用户

发布于 2020-01-01 23:50:03

我们可以通过分配在循环中更新它。

代码语言:javascript
复制
v1 <- c(first(lineups$lineupBefore), rep("", nrow(lineups) -1 ))
for(i in 2:nrow(lineups)) v1[i] <- str_replace(v1[i-1],
          lineups$playerOut[i-1], lineups$playerIn[i-1])
lineups$lineupBefore <- v1
library(dplyr)
lineups %>%
     mutate(lineupAfter = lead(lineupBefore))
# A tibble: 10 x 4
#   lineupBefore                                 playerOut     playerIn     lineupAfter                               
#   <chr>                                        <chr>         <chr>        <chr>                                     
# 1 Justise Winslow, Bam Adebayo, Meyers Leonar… Kendrick Nunn Goran Dragic Justise Winslow, Bam Adebayo, Meyers Leon…
# 2 Justise Winslow, Bam Adebayo, Meyers Leonar… Justise Wins… Derrick Jon… Derrick Jones Jr., Bam Adebayo, Meyers Le…
# 3 Derrick Jones Jr., Bam Adebayo, Meyers Leon… Meyers Leona… Kelly Olynyk Derrick Jones Jr., Bam Adebayo, Kelly Oly…
# 4 Derrick Jones Jr., Bam Adebayo, Kelly Olyny… Bam Adebayo   Justise Win… Derrick Jones Jr., Justise Winslow, Kelly…
# 5 Derrick Jones Jr., Justise Winslow, Kelly O… Tyler Herro   Duncan Robi… Derrick Jones Jr., Justise Winslow, Kelly…
# ...
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59556977

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档