You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

R语言如何自动同步turn列NA值与原数据行首个NA位置

R语言实现按行匹配原数据NA位置自动填充回合列NA

问题描述

我有如下名为m的数据集:

structure(list(id = 1:4, A1 = c(20, 20, 20, 20), B1 = c(20, 20, 
20, 20), A2 = c(10.0873038130365, 4.24227746311085, 4.15920316251515, 
14.466663533707), B2 = c(8.02412449161373, 1.94874394931141, 
12.9319354292045, 18.1870020286129), A3 = c(-2.52545701169281, 
3.91930463167899, -3.22801555234644, 12.175898045939), B3 = c(6.72839637238315, 
0.216884504971863, 9.43932210811731, 10.8221145438518), A4 = c(NA, 
-2.99467608949688, NA, 6.81498054505025), B4 = c(NA, -10.1318519125029, 
NA, 1.91945144708921), A5 = c(NA, NA, NA, -2.53105562138148), 
    B5 = c(NA, NA, NA, -4.39906344008031)), row.names = c(1L, 
4L, 8L, 11L), class = "data.frame", reshapeWide = list(v.names = NULL, 
    timevar = "time", idvar = "id", times = 1:5, varying = structure(c("A1", 
    "B1", "A2", "B2", "A3", "B3", "A4", "B4", "A5", "B5"), .Dim = c(2L, 
    5L))))

数据集预览:

id A1 B1        A2        B2        A3         B3        A4         B4        A5        B5
1   1 20 20 10.087304  8.024124 -2.525457  6.7283964        NA         NA        NA        NA
4   2 20 20  4.242277  1.948744  3.919305  0.2168845 -2.994676 -10.131852        NA        NA
8   3 20 20  4.159203 12.931935 -3.228016  9.4393221        NA         NA        NA        NA
11  4 20 20 14.466664 18.187002 12.175898 10.8221145  6.814981   1.919451 -2.531056 -4.399063

我希望针对每一行(截至该行第一个NA出现的位置为止),创建随机的turn(回合)列(类似游戏中的回合设定),目前手动实现的代码如下:

A_options <- c("red", "blue", "green", "yellow")

A_turn_1 <- sample(A_options, 4, replace=TRUE, prob=c(0.25, 0.25, 0.25, 0.25))
A_turn_2 <- sample(A_options, 4, replace=TRUE, prob=c(0.25, 0.25, 0.25, 0.25))
A_turn_3 <- sample(A_options, 4, replace=TRUE, prob=c(0.25, 0.25, 0.25, 0.25))
A_turn_4 <- sample(A_options, 4, replace=TRUE, prob=c(0.25, 0.25, 0.25, 0.25))
A_turn_5 <- sample(A_options, 4, replace=TRUE, prob=c(0.25, 0.25, 0.25, 0.25))
B_options <- c("grey", "black", "white", "pink")

B_turn_1 <- sample(B_options, 4, replace=TRUE, prob=c(0.25, 0.25, 0.25, 0.25))
B_turn_2 <- sample(B_options, 4, replace=TRUE, prob=c(0.25, 0.25, 0.25, 0.25))
B_turn_3 <- sample(B_options, 4, replace=TRUE, prob=c(0.25, 0.25, 0.25, 0.25))
B_turn_4 <- sample(B_options, 4, replace=TRUE, prob=c(0.25, 0.25, 0.25, 0.25))
B_turn_5 <- sample(B_options, 4, replace=TRUE, prob=c(0.25, 0.25, 0.25, 0.25))

new = cbind(m,A_turn_1,A_turn_2, A_turn_3, A_turn_4, A_turn_5, B_turn_1, B_turn_2, B_turn_3, B_turn_4, B_turn_5)

生成的数据集预览:

id A1 B1        A2        B2        A3         B3        A4         B4        A5        B5 A_turn_1 A_turn_2 A_turn_3 A_turn_4 A_turn_5 B_turn_1 B_turn_2 B_turn_3 B_turn_4 B_turn_5
1   1 20 20 10.087304  8.024124 -2.525457  6.7283964        NA         NA        NA        NA   yellow    green     blue    green   yellow     grey    black    black     pink     grey
4   2 20 20  4.242277  1.948744  3.919305  0.2168845 -2.994676 -10.131852        NA        NA      red      red   yellow    green      red     pink    black    white    black    black
8   3 20 20  4.159203 12.931935 -3.228016  9.4393221        NA         NA        NA        NA     blue      red   yellow     blue     blue     pink     grey    black    white     pink
11  4 20 20 14.466664 18.187002 12.175898 10.8221145  6.814981   1.919451 -2.531056 -4.399063    green   yellow      red      red     blue     pink    white     grey    white     grey

需要实现的规则:对每一行,turn列的NA终止位置需要和原数据行的第一个NA位置保持同步,具体要求:

  • 第1行:A_turn_4、A_turn_5、B_turn_4、B_turn_5替换为NA
  • 第2行:A_turn_5、B_turn_5替换为NA
  • 第3行:A_turn_4、A_turn_5、B_turn_4、B_turn_5替换为NA
  • 第4行:无需替换任何元素为NA

实现方法

核心逻辑是先计算每行第一个NA对应的有效回合数,再批量把超出有效回合的turn列设为NA,不需要手动逐列处理。

第一步:计算每行有效回合数

# 提取所有A、B开头的原始数值列(排除id列)
value_cols <- grep("^[AB]\\d", names(m), value = TRUE)
# 按行查找第一个NA出现的列位置,无NA的行返回列数+1
first_na_pos <- apply(m[value_cols], 1, function(x) {
  na_idx <- which(is.na(x))
  if (length(na_idx) == 0) length(value_cols) + 1 else min(na_idx)
})
# 每回合包含A、B两列,计算每行有效回合数
valid_rounds <- ceiling((first_na_pos - 1) / 2)

计算得到的valid_rounds结果为c(3,4,3,5),和需求完全匹配。

方法1:修改已经生成好的new数据集

如果已经按手动方式生成了全量turn列,可以直接循环逐行替换NA:

# 提取所有A、B类turn列
a_turn_cols <- grep("^A_turn_\\d", names(new), value = TRUE)
b_turn_cols <- grep("^B_turn_\\d", names(new), value = TRUE)

# 逐行替换超出有效回合的位置为NA
for (i in seq_len(nrow(new))) {
  r <- valid_rounds[i]
  if (r < length(a_turn_cols)) {
    new[i, a_turn_cols[(r+1):length(a_turn_cols)]] <- NA
  }
  if (r < length(b_turn_cols)) {
    new[i, b_turn_cols[(r+1):length(b_turn_cols)]] <- NA
  }
}

方法2:直接生成带正确NA的数据集(更简洁)

不需要先生成所有随机值再替换,可以在生成turn列的时候直接把无效位置设为NA,减少冗余计算:

A_options <- c("red", "blue", "green", "yellow")
B_options <- c("grey", "black", "white", "pink")
max_round <- 5

# 循环生成每回合的turn列
for (turn in seq_len(max_round)) {
  # 先生成本回合全量随机值
  m[[paste0("A_turn_", turn)]] <- sample(A_options, nrow(m), replace = TRUE)
  m[[paste0("B_turn_", turn)]] <- sample(B_options, nrow(m), replace = TRUE)
  # 有效回合数小于当前回合的行,直接设为NA
  invalid_rows <- valid_rounds < turn
  m[invalid_rows, paste0("A_turn_", turn)] <- NA
  m[invalid_rows, paste0("B_turn_", turn)] <- NA
}

运行后得到的结果完全符合规则,不需要手动调整每一列。

内容的提问来源于stack exchange,提问作者stats_noob

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 11:42:17