Question

I would like to subset a data frame in order to keep only observations where the seconds are an even number.

You can download a small part of my data here (100 rows).

The first 6 rows look like this:

            Timestamp C01 C02 C03 C04 C05 C06 C07 C08 C09 C10 C11 C12 C13 C14
1 2013-04-01 00:00:00   0   1   1   1   1   0   1   1   1   1   0   1   0   1
2 2013-04-01 00:00:01   0   1   1   1   1   0   1   1   1   1   0   1   0   1
3 2013-04-01 00:00:02   0   1   1   1   1   0   1   1   1   1   0   1   0   1
4 2013-04-01 00:00:03   0   1   1   1   1   0   1   1   1   1   0   1   0   1
5 2013-04-01 00:00:04   0   1   1   1   1   0   1   1   1   1   0   1   0   1
6 2013-04-01 00:00:05   0   1   1   1   1   0   1   1   1   1   0   1   0   1

And I would like it to look like this:

            Timestamp C01 C02 C03 C04 C05 C06 C07 C08 C09 C10 C11 C12 C13 C14
1 2013-04-01 00:00:00   0   1   1   1   1   0   1   1   1   1   0   1   0   1
2 2013-04-01 00:00:02   0   1   1   1   1   0   1   1   1   1   0   1   0   1
3 2013-04-01 00:00:04   0   1   1   1   1   0   1   1   1   1   0   1   0   1
4 2013-04-01 00:00:06   0   1   1   1   1   0   1   1   1   1   0   1   0   1
5 2013-04-01 00:00:08   0   1   1   1   1   0   1   1   1   1   0   1   0   1
6 2013-04-01 00:00:10   0   1   1   1   1   0   1   1   1   1   0   1   0   1

I understand how to subset time intervals from here and here, but I haven't been able to find an example that is similar to my question, and frankly, I have no idea where to start.

Thank you!

Note: The Timestamp variable has already been formatted to POSIXct.

Was it helpful?

Solution 4

Without using any external package, you could do (for even)

res =  df[(as.numeric(substr(df$Timestamp, 18, 19)) %% 2) == 0,]

For testing purposes, I used a small subset of your dataframe:

df = data.frame(Timestamp = c("2013-04-01 00:00:00", "2013-04-01 00:00:01", "2013-04-01 00:00:02", "2013-04-01 00:00:03", "2013-04-01 00:00:04"), C01 = rep(0,5), C02 = rep(1,5))
df$Timestamp = as.POSIXct(df$Timestamp)

Here is what you obtain (for even):

#> res
#            Timestamp C01 C02
#1 2013-04-01 00:00:00   0   1
#3 2013-04-01 00:00:02   0   1
#5 2013-04-01 00:00:04   0   1

For odd, the same logic is applied by replacing ==0 by ==1

OTHER TIPS

I'm adding an answer because, although all answers are nice, none of them acknowledged the fact that POSIXct object, when converted to integers, are in fact expressed in seconds (from the 1st of january 1970), so really the following works as well (but wouldn't if you were trying to picks odd and even minutes, hours,...):

a <- seq(as.POSIXct("2013-04-01 00:00:00"),as.POSIXct("2013-04-01 01:00:00"),by="secs")
a[as.integer(a)%%2==0]
library(lubridate)

foo <- seq(as.POSIXct("2013-01-10"), as.POSIXct("2013-01-11"), by = "secs")

secs <- second(foo)

even <- foo[secs %% 2 == 0]
odd <- foo[secs %% 2 == 1]

Your download link wasn't working for me so I didn't use your data, but you should be able to subset your data.frame in the same way.

A base alternative:

tt <- c(Sys.time(), Sys.time() + 1)
tt
# [1] "2013-10-29 19:43:26 CET" "2013-10-29 19:43:27 CET"

tt[as.numeric(format(tt, "%S")) %% 2 == 0]
# [1] "2013-10-29 19:43:26 CET"

Update with a faster alternative thanks to @Roland

tt[round(as.POSIXlt(tt)$sec) %% 2 == 0]
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top