如何使用mutate()从具有矢量输出的函数中创建多个变量?

时间:2018-08-15 09:29:58

标签: r dplyr lubridate

考虑一个带有两列的小标题A,其中第一列包含时间戳(POSIXct类)和一个Interval对象b,我使用lubridate :: int_diff创建了该对象,其中包含9个单独的时间间隔。

使用dplyr,我想在小标题A上添加9列,表示每行的时间戳是否在任何间隔内。换句话说,我想使用%inin%函数,并在9个新列中分配长度为9的向量输出。

使用dplyr软件包最有效的是什么?

示例:

library(lubridate)
library(dplyr)

A <- tibble(Ts = ymd_hms(c("2018-01-01 15:12:04",
                       "2018-01-02 00:14:06","2018-01-05 12:00:00")),
        P = c(1:3))

ts.start <- ymd_hms("2018-01-01 15:00:00")
ts.end <- ymd_hms("2018-01-02 15:30:00")
ts <- c(ts.start,sort(ts.end - 
                    minutes(cumsum(c(15,15,30,30,60,60,60,60)))),ts.end)

b <- int_diff(ts)

# Applying %within" to the first element works
(A[[1,1]] %within% b) + 0

# The line with error.
mutate(A,New = Ts %within% b )

最后一行会产生预期的错误,并且想知道如何基于将具有矢量输出的函数应用于变量列来定义新变量。

1 个答案:

答案 0 :(得分:2)

如何遍历Ts的每个元素,检查它落在哪个间隔内并将其附加到A上?

# iterate through each element and output a list of matches for each element which
# corresponds to a row
out <- sapply(A$Ts, FUN = function(x, y) x %within% y, y = b, simplify = FALSE)

# append result to original data
cbind(A, do.call(rbind, out))

                   Ts P     1     2     3     4     5     6     7     8     9
1 2018-01-01 15:12:04 1  TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
2 2018-01-02 00:14:06 2  TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
3 2018-01-05 12:00:00 3 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE

您可以使用西葫芦图(刚刚制作的)来可视化该点所属的间隔。

library(ggplot2)

xy <- data.frame(id = 1:length(b), start = int_start(b), end = int_end(b))
head(xy)

ggplot(xy) +
  theme_bw() +
  scale_fill_gradient(low = "#324706", high = "#aeb776") +
  geom_rect(aes(xmin = start, xmax = end, ymin = 0, ymax = nrow(A) + 0.5, fill = id),
            color = "white") +
  geom_hline(yintercept = A$P + 0.5, color = "grey") +
  geom_point(data = A, aes(x = Ts, y = P), color = "white", size = 2) +
  geom_point(data = A, aes(x = Ts, y = P), color = "black", size = 2, shape = 1)

enter image description here