1

我遇到了一个潜在的问题,希望你能帮助我:)

例如,我有以下显示多个商店的数据表,每次访问者进入商店时,都会记录时间和日期。这意味着每一行/每一行都是 1 位进入其中一家商店的访客。

data <- structure(list(store.ID = c("1", "1", "1", "1", "1", 
"2", "2", "2", "2", "2", "3", "3", "3", 
"3", "3", "4", "4", "4", "4", "4"), Time = structure(c(6L, 
7L, 8L, 9L, 10L, 11L, 12L, 13L, 14L, 15L, 1L, 2L, 3L, 4L, 5L, 
16L, 17L, 18L, 19L, 20L), .Label = c("  12:09:19", "  12:09:25", 
"  13:09:30", "  13:09:35", "  14:09:40", " 12:00:03", " 12:00:09", 
" 12:00:14", " 14:00:25", " 16:00:32", " 12:27:19", " 13:27:25", 
" 14:27:41", " 14:27:46", " 17:27:59", " 12:46:10", " 12:46:19", " 13:46:29", 
" 14:46:39", " 15:46:50"), class = "factor"), Date = structure(c(1351728000, 
1351728000, 1351728000, 1351728000, 1351728000, 1351814400, 1351814400, 
1351814400, 1351814400, 1351814400, 1351814400, 1351814400, 1351814400, 
1351814400, 1351814400, 1351814400, 1351814400, 1351814400, 1351814400, 
1351814400), class = c("POSIXct", "POSIXt"), tzone = "UTC")), .Names = c("storeID", "Time", "Date"), class = "data.frame", row.names = c(NA, 
-20L))

[EDIT] The stores are open 24/7. Now I would like is to have a solution / way that assigns each visit / row to one of the 24 hour periods in a day (i.e., 09.00-10.00 being 1, 10.00-11.00 being 2, etc). Then I would like to have the number of visitors per hour period over two consecutive days. I would like to be able to separate this for certain fixed factors, e.g., storeID and City (not shown in this example). Also, if no visitors enter the store, I would like the data file to show that within this time interval there was no visitor, which should in this case return 0). [EDIT]

Note that my data file is huge, having over 700k rows.

I hope I made my issue clear.

MvZB

4

2 回答 2

2

First method:使用Dirk 在这里很好地说明zoo的包。我已经解释了内联代码。这样的事情应该这样做:

df <- data # I just prefer `df` to `data`
df$storeID <- as.numeric(as.character(df$storeID)) # make sure its numeric
# instantiate the zoo object by providing values corresponding to time
require(zoo)
z <- zoo(as.numeric(as.character(df$storeID)), 
              as.POSIXct(paste(df$Date, df$Time)))
# create output data.frame with all possible timings
open_time <- paste(9:18, "00", "00", sep=":")
open_date <- as.character(unique(df$Date))
out.df <- data.frame(Date = rep(open_date, each=length(open_time)-1), 
                     Start = rep(head(open_time, -1), length(open_date)), 
                     End = rep(tail(open_time, -1), length(open_date)))
# Pointer for matching later
out.df$Pointer <- as.POSIXct(paste(out.df$Date, out.df$Start))
# initialise count to 0
out.df$count <- 0

# aggregate using zoo's magic function!
# the first part contains the storeID and is aggregated by
# the second column which creates hourly interval from the times in z (your data)
# and the third column sums up all values that fall in each hourly interval
agg.out <- aggregate(z, time(z) - as.numeric(time(z)) %% 3600, length)

# once that is done, just match the corresponding times and place them rightly
m.idx <- match( out.df$Pointer, index(agg.out))
out.df$count[!is.na(m.idx)] <- agg.out[m.idx[!is.na(m.idx)]]
out.df <- subset(out.df, select=-c(Pointer))

# and you're done
> out.df
#          Date    Start      End count
# 1  2012-11-01  9:00:00 10:00:00     0
# 2  2012-11-01 10:00:00 11:00:00     0
# 3  2012-11-01 11:00:00 12:00:00     0
# 4  2012-11-01 12:00:00 13:00:00     3
# 5  2012-11-01 13:00:00 14:00:00     0
# 6  2012-11-01 14:00:00 15:00:00     1
# 7  2012-11-01 15:00:00 16:00:00     0
# 8  2012-11-01 16:00:00 17:00:00     1
# 9  2012-11-01 17:00:00 18:00:00     0
# 10 2012-11-02  9:00:00 10:00:00     0
# 11 2012-11-02 10:00:00 11:00:00     0
# 12 2012-11-02 11:00:00 12:00:00     0
# 13 2012-11-02 12:00:00 13:00:00     5
# 14 2012-11-02 13:00:00 14:00:00     4
# 15 2012-11-02 14:00:00 15:00:00     4
# 16 2012-11-02 15:00:00 16:00:00     1
# 17 2012-11-02 16:00:00 17:00:00     0
# 18 2012-11-02 17:00:00 18:00:00     1

Second Method:不再从这里使用zoo包装绘图的想法Dirk。但我data.table用于快速访问。再次查看内联注释以获取解释。

require(data.table)
df <- data # I prefer df than data
# create an id column containing only the hours
df$id <- as.numeric(as.POSIXlt(paste(df$Date, df$Time))$hour)
# convert Date to character
df$Date <- as.character(df$Date)

# load package, create input data.table with Date and id as keys
require(data.table)
dt.in <- data.table(df)
setkey(dt.in, "Date", "id")
# get the count of customers / hour / date 
dt.tmp <- dt.in[, .N, by=c("Date", "id")]

# create the output template data.table with Date, Start and End
open_time <- paste(9:18, "00", "00", sep=":")
open_date <- as.character(unique(df$Date))
dt.out <- data.table(Date = rep(open_date, each=length(open_time)-1), 
                     Start = rep(head(open_time, -1), length(open_date)), 
                     End = rep(tail(open_time, -1), length(open_date)))
# create the id again by extracting hour                     
dt.out[, id := as.numeric(as.POSIXlt(paste(Date, Start))$hour)]
setkey(dt.out, "Date", "id")

# merge the two data.tables to get your output
dt.out <- dt.tmp[dt.out, list(Start, End, N)]
dt.out[, id := NULL]

> dt.out
#           Date    Start      End  N
#  1: 2012-11-01  9:00:00 10:00:00 NA
#  2: 2012-11-01 10:00:00 11:00:00 NA
#  3: 2012-11-01 11:00:00 12:00:00 NA
#  4: 2012-11-01 12:00:00 13:00:00  3
#  5: 2012-11-01 13:00:00 14:00:00 NA
#  6: 2012-11-01 14:00:00 15:00:00  1
#  7: 2012-11-01 15:00:00 16:00:00 NA
#  8: 2012-11-01 16:00:00 17:00:00  1
#  9: 2012-11-01 17:00:00 18:00:00 NA
# 10: 2012-11-02  9:00:00 10:00:00 NA
# 11: 2012-11-02 10:00:00 11:00:00 NA
# 12: 2012-11-02 11:00:00 12:00:00 NA
# 13: 2012-11-02 12:00:00 13:00:00  5
# 14: 2012-11-02 13:00:00 14:00:00  4
# 15: 2012-11-02 14:00:00 15:00:00  4
# 16: 2012-11-02 15:00:00 16:00:00  1
# 17: 2012-11-02 16:00:00 17:00:00 NA
# 18: 2012-11-02 17:00:00 18:00:00  1
于 2013-01-26T01:52:00.843 回答
2

这是一个使用 lubridate 和因子的简单解决方案:

library(lubridate)

# Create a single date time variable
dt <- ymd_hms(paste(data$Date, data$Time))
# Extract the day
data$day <- floor_date(dt, "day")
# Extract the hour, converting it into a factor, so we
# get all hours shown
data$hour <- factor(hour(dt), 9:18)

# Count up with table
as.data.frame(table(data[c("day", "hour")]))
于 2013-01-26T14:26:07.070 回答