1

私は潜在的な問題で立ち往生しています、そしてあなたが私を助けてくれることを願っています:)

たとえば、複数の店舗を表示する次のデータテーブルがあり、訪問者が店舗に入るたびに、日時が記録されます。これは、すべての行/行が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))

[編集]店舗は24時間年中無休です。今、私は、各訪問/行を1日の24時間の期間の1つに割り当てるソリューション/方法を用意したいと思います(つまり、09.00-10.00は1、10.00-11.00は2など)。次に、2日間連続して1時間あたりの訪問者数を取得したいと思います。storeIDやCity(この例には示されていません)などの特定の固定要素について、これを分離できるようにしたいと思います。また、来店者がいない場合は、この時間間隔内に来店者がいないことをデータファイルに示してください。この場合は0を返します。 [編集]

私のデータファイルは巨大で、70万行を超えていることに注意してください。

問題を明確にしたいと思います。

MvZB

4

2 に答える 2

2

これは、潤滑剤と因子を使用した簡単な解決策です。

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 に答える
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 に答える