Проценты в год на стоимость - PullRequest
0 голосов
/ 17 декабря 2018

Мои данные

Chemical  date      concentration  limit
A     01-01-2016     0.2         0.01
A     01-02-2016     0.2         0.01
A     01-01-2017     0.005       0.01
A     01-02-2017     0.2         0.01
B     01-01-2016     0.3         0.1
B     01-02-2016     0.05        0.1
B     01-01-2017     0.2         0.1
B     01-02-2017     0.2         0.1
C     01-01-2016     1.2         1
C     01-02-2016     0.8         1
C     01-01-2017     0.9         1
C     01-02-2017     0.9         1

Я хочу показать процентное содержание каждого химического вещества, если оно превышает лимит в год (обратите внимание, что каждый лимит отличается).Итак, я хотел бы получить что-то вроде этого

Year   A         B     C
2016   100%     50%   50%
2017   50%      100%   0

У меня уже есть код для подсчета времени, которое каждый химикат превышает в год, но когда я делаю для процентов, я ошибаюсь.

Это я должен посчитать время.

  library(tidyverse)
   counts<- data %>% 
   group_by(Chemical, grp = format(date, format = '%Y')) %>% 
   mutate(exceed = concentration >= limit) %>% # TRUE/FALSE
   summarise(tot_exceed = sum(exceed)) %>%  # count each T/F
   spread(Chemical, tot_exceed, fill = 0)

, поэтому я получаю это

   Year   A     B    C
   2016   2     1    1
   2017   1     2    0

и для процентов, я попробовал это.

percentage_exceed<- data %>% 
group_by(Chemical, grp = format(date, format = '%Y')) %>% 
mutate(exceed = concentration >= limit, countconc = length(concentration)) 
%>% 
summarise(percent = (sum(exceed)/countconc)*100) %>% 
spread(Chemical, percent, fill = 0)

Но я не получаю желаемого результата.Вы можете мне помочь?

Ответы [ 4 ]

0 голосов
/ 17 декабря 2018

Используя tidyverse и reshape2, вы можете сделать:

df %>%
 mutate(date = str_sub(as.character(date), 7, 10)) %>% #Taking out the year from "date"
 group_by(date, Chemical) %>% #Group by "date" and "Chemical"
 summarise(temp = length(concentration[concentration > limit])/n()*100) %>% #Applying the condition
 dcast(date~Chemical, value.var = "temp") #Reshaping the data

  date   A   B  C
1 2016 100  50 50
2 2017  50 100  0

Или просто tidyverse, используя spread()

df %>%
 mutate(date = str_sub(as.character(date), 7, 10)) %>% #Taking out the year from "date"
 group_by(date, Chemical) %>% #Group by "date" and "Chemical"
 summarise(temp = length(concentration[concentration > limit])/n()*100) %>% #Applying the condition
 spread(Chemical, temp, fill = 0) #Reshaping the data
0 голосов
/ 17 декабря 2018
dt = read.table(text = "
Chemical  date      concentration  limit
A     01-01-2016     0.2         0.01
A     01-02-2016     0.2         0.01
A     01-01-2017     0.005       0.01
A     01-02-2017     0.2         0.01
B     01-01-2016     0.3         0.1
B     01-02-2016     0.05        0.1
B     01-01-2017     0.2         0.1
B     01-02-2017     0.2         0.1
C     01-01-2016     1.2         1
C     01-02-2016     0.8         1
C     01-01-2017     0.9         1
C     01-02-2017     0.9         1
", header=T)

library(tidyverse)
library(lubridate)

dt %>%
  mutate(year = year(dmy(date))) %>%
  group_by(year, Chemical) %>%
  summarise(Total = n(),
            Num_exceed = sum(concentration >= limit)) %>%
  ungroup() %>%
  mutate(Prc = paste0(Num_exceed / Total * 100,"%")) %>%
  select(year, Chemical, Prc) %>%
  spread(Chemical, Prc)

# # A tibble: 2 x 4
#    year A     B     C    
#   <dbl> <chr> <chr> <chr>
# 1  2016 100%  50%   50%  
# 2  2017 50%   100%  0%  
0 голосов
/ 17 декабря 2018

Ваш подход идеально подходит, вам просто нужно заменить sum на mean и умножить на 100:

data %>% group_by(Chemical, grp = format(date, format = '%Y')) %>% 
  mutate(exceed = concentration >= limit) %>% 
  summarise(tot_exceed = mean(exceed) * 100) %>%
  spread(Chemical, tot_exceed, fill = 0)
# A tibble: 2 x 4
#   grp       A     B     C
#   <chr> <dbl> <dbl> <dbl>
# 1 2016    100    50    50
# 2 2017     50   100     0

Строка в вашей попытке

summarise(percent = (sum(exceed)/countconc) * 100)

делает почти так: ошибка связана с тем, что countconc - это целый столбец, а не одно значение (которое необходимо для суммирования).Итак, поскольку в любом случае это столбец константа в каждой группе, вы могли бы написать, например,

summarise(percent = (sum(exceed)/countconc[1]) * 100)

Но, учитывая строку ранее,

mutate(exceed = concentration >= limit, countconc = length(concentration)) 

в конечном итоге это просто среднее значение, поэтому мы возвращаемся к коду в начале моего ответа.

Также обратите внимание, что, используя lubridate, вы можете написать первую строку как

data %>% group_by(Chemical, Year = year(date)) %>% 

Что-то очень краткое, но, возможно, не в том формате, в котором вы хотите

data %>% group_by(Chemical, Year = year(date)) %>% 
  summarise(Percentage = mean(concentration > limit) * 100)
# A tibble: 6 x 3
# Groups:   Chemical [?]
#   Chemical  Year Percentage
#   <fct>    <dbl>      <dbl>
# 1 A         2016        100
# 2 A         2017         50
# 3 B         2016         50
# 4 B         2017        100
# 5 C         2016         50
# 6 C         2017          0
0 голосов
/ 17 декабря 2018

С tidyverse:

library(tidyverse)
library(lubridate)

 data  %>% 
   mutate(yr=mdy(date) %>% year) %>% 
   group_by(Chemical,yr) %>% 
   mutate(exceed  = ifelse(concentration>=limit,1,0  )) %>% 
   summarise(tot_exceed =sum(exceed)) %>% 
   group_by(Chemical) %>% 
   mutate(proc=tot_exceed/max(tot_exceed)*100) %>% 
   select(-tot_exceed) %>% 
   spread(Chemical,proc)
# A tibble: 2 x 4
     yr     A     B     C
  <dbl> <dbl> <dbl> <dbl>
1  2016   100    50   100
2  2017    50   100     0
...