【问题标题】:How can I reduce the code used to create a reproducible dataframe using set.seed() and sample()?如何减少用于使用 set.seed() 和 sample() 创建可重现数据帧的代码?
【发布时间】:2020-04-14 17:54:47
【问题描述】:

我想创建一个名为Activity 的相当大且可重复的数据集,以便在 StackOverFlow 上提出问题。我的数据框将包含变量:

  1. DateTime:日期和时间以毫秒为单位,数据速率为每秒 11 个值,即每秒 11 行。
  2. ID:指个人。我想创建一个包含 3 个人(ABC)的数据集。
  3. x:随机数据,范围从-1到+1。
  4. y:随机数据,范围从-1到+1。
  5. z:从-1到+1的随机数据。

我最初使用这个代码:

set.seed(100)
fmt <- "%Y-%m-%d %H:%M:%OS"

DateTime = seq(from=as.POSIXct("2017-08-05 14:03:55.300", format=fmt, tz="UTC"), by=1/11, length.out=67)
ID = rep("A", each=67)
x= sample(seq(from = -1, to = 1, by = 0.01), size = 67, replace = TRUE)
y= sample(seq(from = -1, to = 1, by = 0.01), size = 67, replace = TRUE)
z= sample(seq(from = -1, to = 1, by = 0.01), size = 67, replace = TRUE)
Activity1<- data.frame(DateTime,ID, x, y, z)

DateTime = seq(from=as.POSIXct("2017-08-05 16:18:12.100", format=fmt, tz="UTC"),by=1/11, length.out=67)
ID = rep("B", each=67)
x= sample(seq(from = -1, to = 1, by = 0.01), size = 67, replace = TRUE)
y= sample(seq(from = -1, to = 1, by = 0.01), size = 67, replace = TRUE)
z= sample(seq(from = -1, to = 1, by = 0.01), size = 67, replace = TRUE)
Activity2<- data.frame(DateTime,ID, x, y, z)

DateTime = seq(from=as.POSIXct("2017-08-05 20:34:31.540", format=fmt, tz="UTC"),by=1/11, length.out=67)
ID = rep("C", each=67)
x= sample(seq(from = -1, to = 1, by = 0.01), size = 67, replace = TRUE)
y= sample(seq(from = -1, to = 1, by = 0.01), size = 67, replace = TRUE)
z= sample(seq(from = -1, to = 1, by = 0.01), size = 67, replace = TRUE)
Activity3<- data.frame(DateTime,ID, x, y, z)
Activity<- rbind(Activity1,Activity2,Activity3)

head(Activity)
                   DateTime ID     x     y     z
1 2017-08-05 14:03:55.29999  A  0.01  0.82 -0.56
2 2017-08-05 14:03:55.39090  A  0.11  0.74  0.07
3 2017-08-05 14:03:55.48182  A  0.50  0.95 -0.64
4 2017-08-05 14:03:55.57273  A  0.97 -0.89  0.95
5 2017-08-05 14:03:55.66364  A -0.97  0.78 -0.01
6 2017-08-05 14:03:55.75454  A -0.46  0.20  1.00

如何使用更少的代码创建相同的数据框?我需要在 StackOverFlow 的另一篇文章中创建一个可重现的数据框,其他用户告诉我应该使用更少的代码来创建我的示例。

【问题讨论】:

  • 他们使用不同的 R 版本吗?据报道,R 3.6 中对 sample 的更改使其无法在版本之间重现 community.rstudio.com/t/getting-different-results-with-set-seed/…
  • 有可能!!你知道如何简化代码来创建我想要的数据框吗??
  • 我使用的是1.2.5033版本。你能检查一下你的,告诉我你是否得到了和我一样的数据框?
  • "我使用的版本是1.2.5033";这很可能是 RStudio 的版本,而不是 R;检查sessionInfo() 的输出你正在使用哪个版本的R
  • 可以使用RNGversion() 函数来获取新版本的 R 以使用旧版本的随机数生成器。例如,RNGversion("3.5.1") 告诉 R 使用 3.5.1 版本的随机数生成器。

标签: r


【解决方案1】:

有许多不同的方法可以达到相同的结果。这就是我使用我喜欢的工具会做的事情:

library(data.table)
# define parameters to control the process
base_data <- fread("DateTime, ID, N
2017-08-05 14:03:55.300, A, 67
2017-08-05 16:18:12.100, B, 67
2017-08-05 20:34:31.540, C, 67")[
  , DateTime := lubridate::ymd_hms(DateTime)]
# expand sequences rowwise
Activity <- base_data[, .(DateTime = seq(from = DateTime, by = 1/11, length.out = N)), 
                      by = .(rn = seq(nrow(base_data)), ID)][
                        , rn := NULL][]
# create x, y, z columns by sampling
cols <- c("x", "y", "z")
set.seed(100)
Activity[,  (cols) := replicate(length(cols), round(runif(.N, -1, +1), 2), simplify = FALSE)]

Activity
     ID            DateTime     x     y     z
  1:  A 2017-08-05 14:03:55 -0.38  0.91 -0.28
  2:  A 2017-08-05 14:03:55 -0.48  0.83 -0.12
  3:  A 2017-08-05 14:03:55  0.10  0.65  0.61
  4:  A 2017-08-05 14:03:55 -0.89 -0.36  0.04
  5:  A 2017-08-05 14:03:55 -0.06  0.76  0.39
 ---                                         
197:  C 2017-08-05 20:34:37 -0.76 -0.52 -0.81
198:  C 2017-08-05 20:34:37  0.20  0.44 -0.59
199:  C 2017-08-05 20:34:37 -0.76 -0.41 -0.94
200:  C 2017-08-05 20:34:37  0.58  0.02  0.16
201:  C 2017-08-05 20:34:37 -0.26 -0.44 -0.69

默认情况下不打印秒的小数部分,但可以通过以下方式验证 1/11 秒的增量

head(diff(Activity$DateTime))
Time differences in secs
[1] 0.09090900 0.09090924 0.09090900 0.09090900 0.09090924 0.09090900

由于 OP 没有要求用我替换的给定种子值准确重现他的结果

sample(seq(from = -1, to = 1, by = 0.01), size = 67, replace = TRUE)

通过

round(runif(.N, -1, +1), 2)

如果sample() 是必需的,seq() 部分可以被跳过

sample((-100:100)/100, .N, replace = TRUE)

使用data.table 链接代码可以更简洁地写成

library(data.table)
cols <- c("x", "y", "z")
set.seed(100)
Activity <- fread("DateTime, ID, N
2017-08-05 14:03:55.300, A, 67
2017-08-05 16:18:12.100, B, 67
2017-08-05 20:34:31.540, C, 67")[
  , DateTime := lubridate::ymd_hms(DateTime)][
    , .(DateTime = seq(from = DateTime, by = 1/11, length.out = N)), 
    by = .(rn = seq(nrow(base_data)), ID)][
      ,  (cols) := replicate(length(cols), round(runif(.N, -1, +1), 2), simplify = FALSE)][
        , rn := NULL][]

【讨论】:

  • 谢谢@Uwe,它看起来棒极了!!有一个疑问,cyldispwt 是什么?您在第一个代码选项之后显示它们。
  • @Dekike 这只是个意外。我已经更正了我的答案。 (显然,我没有正确清理我的工作空间......)
猜你喜欢
  • 2021-08-12
  • 2017-03-18
  • 2023-03-18
  • 2017-11-09
  • 1970-01-01
  • 2013-01-28
  • 1970-01-01
  • 2018-05-17
  • 1970-01-01
相关资源
最近更新 更多