我有一个数据集,显示了一场篮球比赛中的换人情况.第一行的数据有一个变量‘阵容之前’,它告诉我们所有5名球员在换人之前在球场上.

df <- tibble(sub_num = c(1,2,3),
             player_out = c('player_5', 'player_4', 'player_3'),
             player_in = c('player_5', 'player_7', 'player_8'),
             lineupBefore = c('player_1, player_2, player_3, player_4, player_5',NA,NA)
             )

我想要完成的是用一个新的变量‘lineupAfter’填充数据帧,该变量用一个新变量‘lineupAfter’来替换PERAYER_IN的PLAYER_OUT,然后下一行将lineupAfter拉入到NA中的lineupBefore,然后对该行数据执行STR_REPLACE.

希望输出结果如下所示.

df_after <- tibble(sub_num = c(1,2,3),
             player_out = c('player_5', 'player_4', 'player_3'),
             player_in = c('player_6', 'player_7', 'player_8'),
             lineupBefore = c('player_1, player_2, player_3, player_4, player_5','player_1, player_2, player_3, player_4, player_6','player_1, player_2, player_3, player_7, player_6'),
             lineupAfter = c('player_1, player_2, player_3, player_4, player_6', 'player_1, player_2, player_3, player_7, player_6', 'player_1, player_2, player_8, player_7, player_6')
)

我试过了,但我知道它不会起作用,因为我相信变异一次只对一个专栏起作用,不会来回移动.

 df_after <- df %>% 
  mutate(lineupAfter = str_replace(lineupBefore, player_out, player_in),
         lineupBefore = if_else(row_number() != 1, lag(lineupAfter), lineupBefore))

任何指导都将不胜感激!

推荐答案

由于每一行都依赖于更改其前一行的结果after,因此我们需要使用Reducepurrr::reduce进行约简.

我更喜欢使用列表列,因为它提供了更清晰的集合操作,而没有正则表达式的"风险"(诚然,这里没有太多风险).

df %>%
  mutate(
    lineupBefore = strsplit(lineupBefore, "[, ]+"),
    lineupAfter = Reduce(function(prev, rn) c(setdiff(prev, player_out[rn]), player_in[rn]),
                         row_number(), init = lineupBefore[[1]], accumulate=TRUE)[-1], 
    across(starts_with("lineup"), ~ sapply(.x, toString))
  ) %>%
  as.data.frame()
#   sub_num player_out player_in                                     lineupBefore
# 1       1   player_5  player_6 player_1, player_2, player_3, player_4, player_5
# 2       2   player_4  player_7                                               NA
# 3       3   player_3  player_8                                               NA
#                                        lineupAfter
# 1 player_1, player_2, player_3, player_4, player_6
# 2 player_1, player_2, player_3, player_6, player_7
# 3 player_1, player_2, player_6, player_7, player_8

(我在最后添加了as.data.frame,只是为了在控制台渲染上提供完整的字符串,这不是必需的.)

漫游:

  • strsplit(.)将字符串转换为列表列,因此现在第一行是c("player_1", "player_2", "player_3", "player_4", "player_5")(向量),lineupBefore是此类向量的列表;
  • Reduce对一个值和一个向量进行"运算",然后获取结果并对下一个进行运算.由于我们需要对多个列进行操作,因此需要将值作为行号.init=是起始值,在每次调用anon函数时,prev=参数是列表,rn=是行号(使用row_number()提供).
  • Reduce的默认行为是只在最后返回结果;因为我们想要所有的临时值,所以我们添加accumulate=TRUE,并且由于结果比row_number()向量多1(第一个元素是init=值,我们不想要它),所以我们[-1]删除第一个元素.
  • 由于内部无名函数执行的是set-op(setdiffconcatenate),因此顺序并不完全像您所描述的那样,我希望这不是问题.
  • 最后,假设您确实更喜欢使用字符串,我将为您将其恢复为字符串;我可能会将其保留为列表列,这样您就可以删除across(.).

同样的事情,但使用stringr::str_replace:

df %>%
  mutate(
    lineupAfter = Reduce(function(prev, rn) stringr::str_replace(prev, player_out[rn], player_in[rn]),
                         row_number(), init = lineupBefore[[1]], accumulate=TRUE)[-1]
  ) %>%
  as.data.frame()
#   sub_num player_out player_in                                     lineupBefore
# 1       1   player_5  player_6 player_1, player_2, player_3, player_4, player_5
# 2       2   player_4  player_7                                             <NA>
# 3       3   player_3  player_8                                             <NA>
#                                        lineupAfter
# 1 player_1, player_2, player_3, player_4, player_6
# 2 player_1, player_2, player_3, player_7, player_6
# 3 player_1, player_2, player_8, player_7, player_6

R相关问答推荐

从具有随机模式的字符串中提取值

通过绘图 Select 线串几何体并为其着色

无法在我的情节中表现出显着的差异

R创建一个数据透视表,计算多个组的百分比

如何求解arg必须为NULL或deSolve包的ode函数中的字符向量错误

删除列表中存储的数据帧内和数据帧之间的重复行

在连续尺度上转置标签[瀑布图,R]

标识R中多个列中缺少的唯一值

如何写商,水平线,在一个单元格的表在R

如何使用tryCatch执行语句并忽略警告?

如何通过判断数据框的一列来压缩另一列?

try 将 colored颜色 编码添加到ggploly的标题中

合并后返回列表的数据帧列表

列名具有特殊字符时的循环回归

如何使这些react 表对象相互独立?

如何创建累加到现有列累计和的新列?

R代码,用于在线条图下显示观测表

按组和连续id计算日期差

R预测包如何处理ARIMA(Auto.arima函数)中的缺失值

根据向量对列表元素进行排序