我正在构建一个计划程序,用于计算每个人每周工作的小时数。数据框如下所示:
>df
Shift Monday Tuesday Wednesday Thursday Friday Saturday Sunday
1 09-12 a c a c b b b
2 12-15 b d b d a a e
3 15-18 c e c e d e f
4 18-21 d f e f e f a
5 21-24 e a d d c d d
6 24-03 f b f e a b b
7 03-06 a c a a b a e
8 06-09 b d b f d e f
此外,我希望让Shift 24-03服务的人有4小时而不是3小时。所以结果看起来像这样:
name hours
a 30
b 34
c 32
d 31.5
e 34
f 33
答案 0 :(得分:2)
我们可以gather
进入' long'格式,separate
' shift'进入数字列,然后按名称'分组,得到两列的差异sum
library(tidyverse)
gather(df, key, name, -Shift) %>%
separate(Shift, into = c("Start", "End"), convert = TRUE) %>%
mutate(End = ifelse(End < Start, Start + End, End)) %>%
group_by(name) %>%
summarise(hours = sum(End - Start))
答案 1 :(得分:0)
如果您确保列是字符串而非要素,则可以取消列出工作日列以获取普通向量,然后使用table
计算
df <- read.table(text="Shift Monday Tuesday Wednesday Thursday Friday Saturday Sunday
1 09-12 a c a c b b b
2 12-15 b d b d a a e
3 15-18 c e c e d e f
4 18-21 d f e f e f a
5 21-24 e a d d c d d
6 24-03 f b f e a b b
7 03-06 a c a a b a e
8 06-09 b d b f d e f",
stringsAsFactors = FALSE)
plain_vec <- unlist(df[,2:8], use.names = FALSE)
这会让你
> table(plain_vec)
plain_vec
a b c d e f
11 11 6 10 10 8
要计算小时数,您可以按照小时数复制行,并通过为此添加额外行来调整24-03。
> table(unlist(df[c(rep(c(1:5,7:8), each=3), rep(8,4)), 2:8], use.names=FALSE))
a b c d e f
30 32 18 38 31 26
use.names=FALSE
只是我通常用unlist
做的事情。你不需要它,但如果矢量不必随身携带它们的名字,你的代码通常会快得多。
答案 2 :(得分:0)
我认为gather
包中的tidyr
会将数据整形为您想要的形式:
> df1 = df %>% tidyr::gather(key = "weekday", value = "name", -Shift)
Shift weekday name
1 09-12 Monday a
2 12-15 Monday b
3 15-18 Monday c
4 18-21 Monday d
...
然后,您可以使用hours
和mutate
添加ifelse
列:
df2 = df1 %>% mutate(hours = ifelse(Shift == "24-03", 4, 3))
答案很简单group_by
/ summarise
组合:
answer = df2 %>% group_by(name) %>% summarise(hours = sum(hours))
answer
数据框如下所示:
name hours
-----------
a 34
b 36
c 18
d 30
e 31
f 26
这不是你想要的,但我认为你的样本数据有些可疑。怎么有人有31.5个小时?