Skip to content

Storing business hours

6 messages · alexander.sommer at tu-dortmund.de, Jim Lemon, William Dunlap

#
Hi fellow R-users,

I am wondering about the best way to store business hours and the like in R. (Best in the sense of best for analyzing them.)

Say, I got a number of ?shops?:
Shop A opens at 8am and closes at 8pm;
shop B opens at 9am, closes at 11.45am for a siesta, reopens at 1.30pm and closes at 5pm;
and so forth.

To simplify things, I would assume that closing a shop for more than two times and reopening it for more than one time is not possible. (Hoping to avoid problems with shops having multiple siestas and business hours beyond midnight this way.)

My first idea would be to plot something like an empirical distribution function for this data. (Having only shops A and B, this would be zero until 8am, 50?% from 8am to 9am, 100?% from 9am to 11.45am, 50?% again from 11.45am to 1.30pm, 100?% again from 1.30pm to 5pm, yet again 50?% from 5pm to 8pm and falling back to zero from 8pm on.) But general arithmetic should be possible, especially for building a mean over some days.

Any ideas?

Cheers,

Alex


--
Alexander Sommer
wissenschaftlicher Mitarbeiter

Technische Universit?t Dortmund
Fakult?t Erziehungswissenschaft, Psychologie und Soziologie
Forschungsverbund Deutsches Jugendinstitut/Technische Universit?t Dortmund
Vogelpothsweg 78
44227 Dortmund

Telefon: +49 231 755-8189
Telefax: +49 231 755-6553
E-Mail:  alexander.sommer at tu-dortmund.de
WWW:     http://www.forschungsverbund.tu-dortmund.de/


Wichtiger Hinweis: Die Information in dieser E-Mail ist vertraulich. Sie ist ausschlie?lich f?r den Adressaten bestimmt. Sollten Sie nicht der f?r diese E-Mail bestimmte Adressat sein, unterrichten Sie bitte den Absender und vernichten Sie diese Mail. Vielen Dank.
Unbeschadet der Korrespondenz per E-Mail, sind unsere Erkl?rungen ausschlie?lich final rechtsverbindlich, wenn sie in herk?mmlicher Schriftform (mit eigenh?ndiger Unterschrift) oder durch ?bermittlung eines solchen Schriftst?cks per Telefax erfolgen.

Important note: The information included in this e-mail is confidential. It is solely intended for the recipient. If you are not the intended recipient of this e-mail please contact the sender and delete this message. Thank you. Without prejudice of e-mail correspondence, our statements are only legally binding when they are made in the conventional written form (with personal signature) or when such documents are sent by fax.
#
Hi Alexander,
A time series comes to mind, but perhaps all you need is a matrix with
0s for closed and 1s for open. Each row is a shop. Column names as the
times and the resolution is up to you. I think colSums will produce
what you want.

Jim

On Fri, Aug 26, 2016 at 1:10 AM, alexander.sommer at tu-dortmund.de
<alexander.sommer at tu-dortmund.de> wrote:
#
If you label opening times with +1 and closing times with -1 then
cumsum(thoseLabels) will tell you how many shops are open immediately after
each of those times.  You can use findInterval() on the times to map an
arbitrary time to the number of shops open at that time.  You do need to
deal with starting values so that the first label for each shop is +1.

Bill Dunlap
TIBCO Software
wdunlap tibco.com
On Thu, Aug 25, 2016 at 3:14 PM, Jim Lemon <drjimlemon at gmail.com> wrote:

            

  
  
3 days later
#
Cheers Jim!

The 0/1 way seems to work for me. It looks like:

n <-  5   # number of ?shops?
i <- 12   # number of time intervals per hour

# creating a data.frame (the example got random values)
business_hours <- data.frame(1:n, matrix(data = sample(x = c(TRUE, FALSE), size = n * (24 * i), replace = TRUE), ncol = 24 * i))
# column names as the times
colnames(x = business_hours) <- c("Id", paste0("t", sprintf(fmt = "%02d", rep(x = 0:23, each = i)), sprintf(fmt = "%02d", rep(x = seq(from = 0, to = 60/i * (i - 1), by = 60/i), times = 24))))

# some data analysis
plot(x = colSums(x = business_hours[, -1]), type = "s")  # looks odd due to the random assignment of open/closed
summary(object = rowSums(x = business_hours[, -1])/i)    # summary of business duration in hours

Best regards,

Alex


--
Alexander Sommer
wissenschaftlicher Mitarbeiter

Technische Universit?t Dortmund
Fakult?t Erziehungswissenschaft, Psychologie und Soziologie
Forschungsverbund Deutsches Jugendinstitut/Technische Universit?t Dortmund
Vogelpothsweg 78
44227 Dortmund

Telefon: +49 231 755-8189
Telefax: +49 231 755-6553
E-Mail:  alexander.sommer at tu-dortmund.de
WWW:     http://www.forschungsverbund.tu-dortmund.de/

Wichtiger Hinweis: Die Information in dieser E-Mail ist vertraulich. Sie ist ausschlie?lich f?r den Adressaten bestimmt. Sollten Sie nicht der f?r diese E-Mail bestimmte Adressat sein, unterrichten Sie bitte den Absender und vernichten Sie diese Mail. Vielen Dank.
Unbeschadet der Korrespondenz per E-Mail, sind unsere Erkl?rungen ausschlie?lich final rechtsverbindlich, wenn sie in herk?mmlicher Schriftform (mit eigenh?ndiger Unterschrift) oder durch ?bermittlung eines solchen Schriftst?cks per Telefax erfolgen.

Important note: The information included in this e-mail is confidential. It is solely intended for the recipient. If you are not the intended recipient of this e-mail please contact the sender and delete this message. Thank you. Without prejudice of e-mail correspondence, our statements are only legally binding when they are made in the conventional written form (with personal signature) or when such documents are sent by fax.
#
Dear Bill,

thank you for your help. I think, I finally understood your advice. At least, this one worked:

library(package = lubridate)   # for a more convenient display of times

i <- 12   # number of time intervals per hour

# creating a data.frame (original example)
business_hours <- data.frame(t = hm(paste(rep(x = 0:23, each = i), rep(x = seq(from = 0, to = 60/i * (i - 1), by = 60/i), times = 24))),
                             A = c(rep(x = 0, times = (8 - (1/i)) * i), 1, rep(x = 0, times = (12   - (1/i)) * i), -1, rep(x = 0, times = (4           ) * i)),
                             B = c(rep(x = 0, times = (9 - (1/i)) * i), 1, rep(x = 0, times = (2.75 - (1/i)) * i), -1, rep(x = 0, times = (1.75 - (1/i)) * i), 1, rep(x = 0, times = (3.5 - (1/i)) * i), -1, rep(x = 0, times = 7 * i)))

# some data analysis
plot(x = rowSums(x = cumsum(business_hours[, -1])), type = "s")

I find some elegance in this solution; still, Jims proposal looks easier to handle to me.

Best regards,

Alex


--
Alexander Sommer
wissenschaftlicher Mitarbeiter

Technische Universit?t Dortmund
Fakult?t Erziehungswissenschaft, Psychologie und Soziologie
Forschungsverbund Deutsches Jugendinstitut/Technische Universit?t Dortmund
Vogelpothsweg 78
44227 Dortmund

Telefon: +49 231 755-8189
Telefax: +49 231 755-6553
E-Mail:  alexander.sommer at tu-dortmund.de
WWW:     http://www.forschungsverbund.tu-dortmund.de/
Wichtiger Hinweis: Die Information in dieser E-Mail ist vertraulich. Sie ist ausschlie?lich f?r den Adressaten bestimmt. Sollten Sie nicht der f?r diese E-Mail bestimmte Adressat sein, unterrichten Sie bitte den Absender und vernichten Sie diese Mail. Vielen Dank.
Unbeschadet der Korrespondenz per E-Mail, sind unsere Erkl?rungen ausschlie?lich final rechtsverbindlich, wenn sie in herk?mmlicher Schriftform (mit eigenh?ndiger Unterschrift) oder durch ?bermittlung eines solchen Schriftst?cks per Telefax erfolgen.

Important note: The information included in this e-mail is confidential. It is solely intended for the recipient. If you are not the intended recipient of this e-mail please contact the sender and delete this message. Thank you. Without prejudice of e-mail correspondence, our statements are only legally binding when they are made in the conventional written form (with personal signature) or when such documents are sent by fax.
#
The cummax(+-1) trick, along with findInterval(), is most useful for
expanding a list of opening and closing times into a table which can be
used to find the number of open shops at any given time.  E.g., suppose
your raw data comes from business hours posted on web sites:

shopHours <- list(Butcher=rbind(c(Open=8,Close=12), c(13, 17)),
                  Florist=rbind(c(Open=10,Close=18)),
                  Pub=rbind(c(Open=10,Close=14), c(16,22)),
                  Bank=rbind(c(Open=9,Close=15)))

Then you can generate a list of the number of open shops at any time with:

d <- data.frame(Shop=rep(names(shopHours), vapply(shopHours,nrow,0)),
do.call("rbind", shopHours))
d <- with(d, rbind(data.frame(Shop, Hour=Open, Action=+1), data.frame(Shop,
Hour=Close, Action=-1)))
d <- d[order(d$Hour),]
d$NumberOpen <- cumsum(d$Action)
transform(data.frame(Hour=seq(8,22,by=1),
NumberOpen=d$NumberOpen[findInterval(Hour, d$Hour)])
#   Hour NumberOpen
#1     8          1
#2     9          2
#3    10          4
#4    11          4
#5    12          3
#6    13          4
#...


Bill Dunlap
TIBCO Software
wdunlap tibco.com

On Mon, Aug 29, 2016 at 8:06 AM, alexander.sommer at tu-dortmund.de <
alexander.sommer at tu-dortmund.de> wrote: