Reputation: 41
I have a data frame with a specific variable (Var1) and a time variable (Var2).
I would like to calculate the frequency of occurrence (Frequency) of Var1 withing a specific time step (let say 1 min) during a year.
sample dataset:
Var1 <- c(rep("A", 4), rep("B", 3), rep("C", 2))
Var2 <- c("2018-09-01 10:00:00", "2018-09-01 10:00:30", "2018-09-01 10:00:45",
"2018-09-10 22:10:00", "2017-09-05 10:54:30", "2018-12-15 10:00:30",
"2018-12-15 10:01:00", "2017-02-20 17:16:30", "2017-12-20 20:08:56")
df <- data.frame(Var1, Var2)
df$Var2 <- as.POSIXct(df$Var2)
desired output:
Frequency <- c(rep(3, 3), rep(1, 2), rep(2,2), rep(1,2))
dfOut <- data.frame(Var1, Var2, Frequency)
# Var1 Var2 Frequency
#1 A 2018-09-01 10:00:00 3
#2 A 2018-09-01 10:00:30 3
#3 A 2018-09-01 10:00:45 3
#4 A 2018-09-10 22:10:00 1
#5 B 2017-09-05 10:54:30 1
#6 B 2018-12-15 10:00:30 2
#7 B 2018-12-15 10:01:00 2
#8 C 2017-02-20 17:16:30 1
#9 C 2017-12-20 20:08:56 1
Upvotes: 2
Views: 416
Reputation: 15062
You can use lubridate::floor_date
to get the minute grouping column that accounts for date as you are describing. Note that your displayed desired output does not seem to match your comment
Var1 <- c(rep("A", 4), rep("B", 3), rep("C", 2))
Var2 <- c("2018-09-01 10:00:00", "2018-09-01 10:00:30", "2018-09-01 10:00:45",
"2018-09-10 22:10:00", "2017-09-05 10:54:30", "2018-12-15 10:00:30",
"2018-12-15 10:01:00", "2017-02-20 17:16:30", "2017-12-20 20:08:56")
df <- data.frame(Var1, Var2)
df$Var2 <- as.POSIXct(df$Var2)
library(tidyverse)
library(lubridate)
df %>%
mutate(minute = floor_date(Var2, unit = "minute")) %>%
add_count(Var1, minute)
#> # A tibble: 9 x 4
#> Var1 Var2 minute n
#> <fct> <dttm> <dttm> <int>
#> 1 A 2018-09-01 10:00:00 2018-09-01 10:00:00 3
#> 2 A 2018-09-01 10:00:30 2018-09-01 10:00:00 3
#> 3 A 2018-09-01 10:00:45 2018-09-01 10:00:00 3
#> 4 A 2018-09-10 22:10:00 2018-09-10 22:10:00 1
#> 5 B 2017-09-05 10:54:30 2017-09-05 10:54:00 1
#> 6 B 2018-12-15 10:00:30 2018-12-15 10:00:00 1
#> 7 B 2018-12-15 10:01:00 2018-12-15 10:01:00 1
#> 8 C 2017-02-20 17:16:30 2017-02-20 17:16:00 1
#> 9 C 2017-12-20 20:08:56 2017-12-20 20:08:00 1
Created on 2018-09-11 by the reprex package (v0.2.0).
Upvotes: 1
Reputation: 25225
Here is a data.table
approach. You can first create an index showing if the datetime for next row is 1 min after the datetime of current row. Then, use this as one of the grouping criteria to calculate the frequency.
library(data.table)
setDT(df)[, idx := cumsum(c(0L, Var2[-1L] > Var2[-.N] + 60L)), by=.(Var1)][,
Freq := .N, by=.(Var1, idx)]
output:
Var1 Var2 idx Freq
1: A 2018-09-01 10:00:00 0 3
2: A 2018-09-01 10:00:30 0 3
3: A 2018-09-01 10:00:45 0 3
4: A 2018-09-10 22:10:00 1 1
5: B 2017-09-05 10:54:30 0 1
6: B 2018-12-15 10:00:30 1 2
7: B 2018-12-15 10:01:00 1 2
8: C 2017-02-20 17:16:30 0 1
9: C 2017-12-20 20:08:56 1 1
Upvotes: 0
Reputation: 69
You can do something like this. Create a new character vector to define the groups, then group by Var1 and the new variable. This doesn't give exactly your desired output because the minutes are defined differently.
library(dplyr)
df %>%
mutate(minute = substring(as.character(Var2), 1, 16)) %>%
group_by(Var1, minute) %>%
mutate(frequency = n())
Upvotes: 0