在 R 中的循环中使用开始值和结束值的示例

Sample using start and end values within a loop in R

我正在尝试在一系列值之间进行采样,作为 R 中较大循环的一部分。随着循环进行到每一行 j,我想在 start 列和 end 列中给出的值,将该值放在该行的 sampled 列中。

结果应如下所示:

ID  start  end  sampled
a   25     67   44
b   36     97   67
c   23     85   77
d   15     67   52
e   21     52   41
f   43     72   66
g   39     55   49
h   27     62   35
i   11     99   17
j   21     89   66
k   28     65   48
l   44     58   48
m   16     77   22
n   25     88   65

我开始使用 mapply,它对整个 df 进行采样,但后来我试图将所有 15 个采样值放入一行。

df[j,4] <- mapply(function(x, y) sample(seq(x, y), 1), df$start, df$end)

我想也许使用 seq 的东西可能会起作用,但这会导致错误提示 from 的长度必须为 1。

df[j,4] <- sample(seq(df$start, df$end),1,replace=TRUE)

外部循环结构非常复杂,因此我没有在此处包含它,但是代码的 df[j,4] 部分是必需的,因为它是更大循环的一部分。在某些情况下,必须根据实际数据集中的其他依赖项对行进行重新采样。例如,a 的采样值可能需要大于 b。其余代码更新采样列,检查依赖项,如果不满足依赖项,将重新运行示例。如果我能让这个采样部分工作,我应该可以毫不费力地插入它(我希望)。

这是一个示例数据集。

structure(list(ID = c("a", "b", "c", "d", "e", "f", "g", "h", 
"i", "j", "k", "l", "m", "n"), start = c(25, 36, 23, 15, 21, 
43, 39, 27, 11, 21, 28, 44, 16, 25), end = c(67, 97, 85, 67, 
52, 72, 55, 62, 99, 89, 65, 58, 77, 88), sampled = c(NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA)), class = c("spec_tbl_df", 
"tbl_df", "tbl", "data.frame"), row.names = c(NA, -14L), spec = structure(list(
    cols = list(ID = structure(list(), class = c("collector_character", 
    "collector")), start = structure(list(), class = c("collector_double", 
    "collector")), end = structure(list(), class = c("collector_double", 
    "collector")), sampled = structure(list(), class = c("collector_logical", 
    "collector"))), default = structure(list(), class = c("collector_guess", 
    "collector")), skip = 1), class = "col_spec"))```

首先,将数据置于更易于与dput(df)一起使用的格式:

df <- structure(list(ID = structure(1:14, .Label = c("a", "b", "c", 
    "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n"), class = "factor"), 
    start = c(25L, 36L, 23L, 15L, 21L, 43L, 39L, 27L, 11L, 21L, 
    28L, 44L, 16L, 25L), end = c(67L, 97L, 85L, 67L, 52L, 72L, 
    55L, 62L, 99L, 89L, 65L, 58L, 77L, 88L), sampled = c(44L, 
    67L, 77L, 52L, 41L, 66L, 49L, 35L, 17L, 66L, 48L, 48L, 22L, 
    65L)), class = "data.frame", row.names = c(NA, -14L))

你与 mapply() 非常接近,但你让它变得比需要的更难:

df$sampled <- mapply(function(x, y) sample(seq(x, y), 1), df$start, df$end)
df
#    ID start end sampled
# 1   a    25  67      67
# 2   b    36  97      86
# 3   c    23  85      54
# 4   d    15  67      36
# 5   e    21  52      37
# 6   f    43  72      60
# 7   g    39  55      44
# 8   h    27  62      37
# 9   i    11  99      86
# 10  j    21  89      52
# 11  k    28  65      65
# 12  l    44  58      51
# 13  m    16  77      62
# 14  n    25  88      31

您可能不需要循环。如果你想要的是介于开始和结束之间的东西,它几乎等同于对 0-1 之间的东西进行采样并将其乘以范围。

df %>% mutate(sampled = start + round((end-start)*runif(nrow(.))))

关于更新,您在评论中提到的依赖项:听起来有点复杂。 快速思考:可能会更快地采样很多次并选择一个符合您标准的。

想通了。 df[j,4] <- mapply(function(x, y) sample(seq(x, y), 1), df[j,"start"], df[j,"end"])

我只需要具体说明我想输入哪一行采样值 df[j,4]。为列 startend 指定行 j 就可以了。