【问题标题】:How to transform a dataset in R?如何在 R 中转换数据集?
【发布时间】:2020-01-12 13:08:46
【问题描述】:

为了我的工作,我正在尝试编写一些代码来计算所需的停车位数量。我有关于每小时到达的汽车数量以及停车场上每辆车的停车时间(通过 rnorm 生成)的数据。现在我想计算每分钟需要多少停车位。

(小时和吸引力强度变量)

timeonparking <- round(rnorm(14, mean = 35, sd = 10))

首先,我想为 0-59 之间的每一行/小时生成 X 个数字(均匀分布;表示在给定小时内到达的分钟数),其中 X 等于该小时的吸引强度。

新的数据框应该如下所示:

有人可以帮帮我吗?我的第一个想法是使用 for 循环。但这不会导致上面显示的表格,并且代码包含我找不到的错误(我是 R 的初学者)。我不知道如何转换数据集。

第一次尝试:

for (i in nrow(df) {
    df1 <- paste(df$ï..hour[i], list(runif(df$attraction_vehicles[i], min = 0, max = 59)))
}

【问题讨论】:

  • 欢迎来到 Stack Overflow!您能否通过分享您的数据样本来重现您的问题,以便其他人可以提供帮助(请不要使用str()head() 或屏幕截图)?您可以使用 reprexdatapasta 包来帮助您。另见Help me Help you & How to make a great R reproducible example?
  • 三件事:(1)listpaste中的使用是不必要的,你有什么理由? (2) 尽管数据图像没有,但您的代码包含 unicode 列名似乎很奇怪。 (3) 当包含具有某种形式随机性的样本数据时,从已知点开始确实很有帮助,请使用set.seed,以便验证您的中间步骤。
  • @Tung 这是我第一次听说datapasta 包——看起来棒极了! OP:您可能对以下相关问题感兴趣:stackoverflow.com/questions/19518728/…

标签: r


【解决方案1】:

有几种方法可以解决这个问题,但让我们从一个已知点开始:

dat <- data.frame(
  hour = c("5:00:00", "6:00:00", "7:00:00"),
  attraction = c(1, 3, 6)
)
dat$hour <- as.POSIXct(dat$hour, format = "%H:%M:%S")
dat
#                  hour attraction
# 1 2020-01-12 05:00:00          1
# 2 2020-01-12 06:00:00          3
# 3 2020-01-12 07:00:00          6

由于您希望进行基于时间的计算,我将hour 设置为POSIXt 类型。 (如果您的数据中也有“日期”部分,则需要将其包含在转换中,但如果总是在同一天,那么它似乎并不重要。)

从这里,我们可以为每次到达引入随机分钟数:

set.seed(42)
dat2 <- do.call(
  "rbind.data.frame",
  Map(function(hr, n) data.frame(hour = hr, min = round(runif(n, min = 0, max = 59))),
      dat$hour, dat$attraction)
)
dat2
#                   hour min
# 1  2020-01-12 05:00:00  54
# 2  2020-01-12 06:00:00  55
# 3  2020-01-12 06:00:00  17
# 4  2020-01-12 06:00:00  49
# 5  2020-01-12 07:00:00  38
# 6  2020-01-12 07:00:00  31
# 7  2020-01-12 07:00:00  43
# 8  2020-01-12 07:00:00   8
# 9  2020-01-12 07:00:00  39
# 10 2020-01-12 07:00:00  42

我不知道你是单独需要分钟还是实时,所以也许

dat2$arrival_time <- dat2$hour + (60 * dat2$min)
dat2
#                   hour min        arrival_time
# 1  2020-01-12 05:00:00  54 2020-01-12 05:54:00
# 2  2020-01-12 06:00:00  55 2020-01-12 06:55:00
# 3  2020-01-12 06:00:00  17 2020-01-12 06:17:00
# 4  2020-01-12 06:00:00  49 2020-01-12 06:49:00
# 5  2020-01-12 07:00:00  38 2020-01-12 07:38:00
# 6  2020-01-12 07:00:00  31 2020-01-12 07:31:00
# 7  2020-01-12 07:00:00  43 2020-01-12 07:43:00
# 8  2020-01-12 07:00:00   8 2020-01-12 07:08:00
# 9  2020-01-12 07:00:00  39 2020-01-12 07:39:00
# 10 2020-01-12 07:00:00  42 2020-01-12 07:42:00

我应该注意,您使用 rnorm "can" 会导致负分钟数,因为它是渐近无限的;使用sd=10 当然会降低可能性,但是如果您需要随机到达时间“始终”在指定的小时内,那么您使用runif 会更好,或者您可以考虑截断正态分布,例如提供通过truncnorm 包。

注意:我使用Map,它是lapply 的多参数版本。使用 R 的 apply 系列中的函数通常具有优势(有时在性能方面,有时在可读性方面),虽然性能优势大部分已被减轻(历史上 for 通常比 sapply 慢),但仍有一些人发现 @987654339 @ 更好的。对于Map,我写了一些答案来解释(通过“展开”它)它是如何工作的:https://stackoverflow.com/a/57367292https://stackoverflow.com/a/54485425


要获得入住率(给定时间段内有多少辆车),我建议您使用cut 来分类到达时间。我们可以通过以下方式创建 bin 边界:

myseq <- round(range(dat2$arrival_time) + c(-1800,1800), "hour")
myseq
# [1] "2020-01-12 05:00:00 PST" "2020-01-12 08:00:00 PST"

myseq <- seq.POSIXt(myseq[1], myseq[2], by = "min")
length(myseq)
# [1] 181

myseq <- myseq[seq_along(myseq) %% 10 == 1]
myseq
#  [1] "2020-01-12 05:00:00 PST" "2020-01-12 05:10:00 PST" "2020-01-12 05:20:00 PST"
#  [4] "2020-01-12 05:30:00 PST" "2020-01-12 05:40:00 PST" "2020-01-12 05:50:00 PST"
#  [7] "2020-01-12 06:00:00 PST" "2020-01-12 06:10:00 PST" "2020-01-12 06:20:00 PST"
# [10] "2020-01-12 06:30:00 PST" "2020-01-12 06:40:00 PST" "2020-01-12 06:50:00 PST"
# [13] "2020-01-12 07:00:00 PST" "2020-01-12 07:10:00 PST" "2020-01-12 07:20:00 PST"
# [16] "2020-01-12 07:30:00 PST" "2020-01-12 07:40:00 PST" "2020-01-12 07:50:00 PST"
# [19] "2020-01-12 08:00:00 PST"

first 命令 查找时间范围并将其out 舍入到下一小时。 (+c(-1800,1800) 的使用确保回合将分别给我们一个地板和天花板。这可能会发现不完美的极端情况,但它应该在大多数情况下工作。) 第二个命令创建一个每分钟的序列,此处为 181 长(三个小时)。 第三条命令 将其缩短为每 10 分钟一次。

您应该能够根据需要轻松调整这三个命令。

从这里,你可以使用

cut(dat2$arrival_time, myseq)
#  [1] 2020-01-12 05:50:00 2020-01-12 06:50:00 2020-01-12 06:10:00 2020-01-12 06:40:00
#  [5] 2020-01-12 07:30:00 2020-01-12 07:30:00 2020-01-12 07:40:00 2020-01-12 07:00:00
#  [9] 2020-01-12 07:30:00 2020-01-12 07:40:00
# 18 Levels: 2020-01-12 05:00:00 2020-01-12 05:10:00 2020-01-12 05:20:00 ... 2020-01-12 07:50:00

它会告诉您每次到达属于哪个 10 分钟垃圾箱。快速总结可以用

table(cut(dat2$arrival_time, myseq))
# 2020-01-12 05:00:00 2020-01-12 05:10:00 2020-01-12 05:20:00 2020-01-12 05:30:00 
#                   0                   0                   0                   0 
# 2020-01-12 05:40:00 2020-01-12 05:50:00 2020-01-12 06:00:00 2020-01-12 06:10:00 
#                   0                   1                   0                   1 
# 2020-01-12 06:20:00 2020-01-12 06:30:00 2020-01-12 06:40:00 2020-01-12 06:50:00 
#                   0                   0                   1                   1 
# 2020-01-12 07:00:00 2020-01-12 07:10:00 2020-01-12 07:20:00 2020-01-12 07:30:00 
#                   1                   0                   0                   3 
# 2020-01-12 07:40:00 2020-01-12 07:50:00 
#                   2                   0 

【讨论】:

  • 非常感谢您的帮助。这段代码很好地定义了我的间隔边界。我可以问你一个后续问题吗?我想计算每分钟(1 - 1440 分钟)所需的停车位数量。 x
  • 查看我的编辑。如果它变得更复杂,您可能需要一个新问题。
  • 菲利普,这能回答你的问题吗?如果有,请accept it
  • 很抱歉回答迟了。该代码有效。感谢您的帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-08-31
  • 1970-01-01
  • 1970-01-01
  • 2013-12-09
  • 1970-01-01
  • 2017-10-07
  • 1970-01-01
相关资源
最近更新 更多