如何计算R中数据框中的唯一值

时间:2018-03-22 05:55:38

标签: r dataframe

我正在构建一个计划程序,用于计算每个人每周工作的小时数。数据框如下所示:

>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

3 个答案:

答案 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
...

然后,您可以使用hoursmutate添加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个小时?