我有一个看起来像这样的数据框:
Date Type Count
<date> <fct> <int>
1 2018-11-01 B 2
2 2018-11-01 A 4
3 2018-11-02 A 1
4 2018-11-03 A 4
5 2018-11-04 A 3
6 2018-11-05 A 2
7 2018-11-06 C 1
8 2018-11-06 A 1
9 2018-11-07 A 1
对于数据框中的每个日期,可能存在或可能不存在3种可能的类型(A,B,C)(即Count可以为0)。
我想计算每天A和C之间的每日百分比差异:
即(A-C)/(A + B + C)* 100%
例如,对于2018-11-01(A = 4,B = 2,C = 0),百分比差异应为:(4-0)/ 6 * 100%= 66.7%
结果表应为:
Date Count
<date> <int>
1 2018-11-01 66.7%
2 2018-11-02 some %
3 2018-11-03 some %
4 2018-11-04 some %
5 2018-11-05 some %
6 2018-11-06 some %
7 2018-11-07 some %
我是否有一种方法可以计算此结果(也许使用dplyr包)而不必使用R中的for或foreach循环遍历每个日期?
我试图做这样的事情,但是它没有考虑到A,B和C的计数为0(即数据帧中缺失)的可能性:
abc %>% group_by(DATE) %>%
arrange(DATE) %>%
mutate(diff = n - lag(n, default = first(n)))
答案 0 :(得分:1)
我们可以使用complete
使用Type
用fill = 0
用0填充丢失的Date
,然后执行计算。假设每个library(tidyverse)
df %>%
group_by(Date) %>%
complete(Type, fill = list(Count = 0)) %>%
summarise(Count = (Count[Type == "A"] - Count[Type == "C"])/sum(Count))
# Date Count
# <fct> <dbl>
#1 2018-11-01 0.667
#2 2018-11-02 1
#3 2018-11-03 1
#4 2018-11-04 1
#5 2018-11-05 1
#6 2018-11-06 0
#7 2018-11-07 1
的“ A”,“ B”和“ C”最多只有一个值。
instanceof
答案 1 :(得分:1)
对于这样的计算,我更喜欢将形状重塑为宽的形状,这样我就可以直接访问我要区别的列,即具有A,B和C列。这有点冗长,但这给了我更好地处理数据中的内容。
类似于@Ronak Shah的答案,我首先使用complete
之类的东西来填写日期和类型的任何缺失组合。我还要按组汇总计数,以防万一对任何日期类型组合有多个观察结果。
library(tidyverse)
df_complete <- df %>%
group_by(Date, Type) %>%
summarise(Count = sum(Count)) %>%
ungroup() %>%
complete(Date, Type, fill = list(Count = 0))
df_complete
#> # A tibble: 21 x 3
#> Date Type Count
#> <date> <chr> <dbl>
#> 1 2018-11-01 A 4
#> 2 2018-11-01 B 2
#> 3 2018-11-01 C 0
#> 4 2018-11-02 A 1
#> 5 2018-11-02 B 0
#> 6 2018-11-02 C 0
#> 7 2018-11-03 A 4
#> 8 2018-11-03 B 0
#> 9 2018-11-03 C 0
#> 10 2018-11-04 A 3
#> # ... with 11 more rows
然后使用spread
,获取每种类型的列,然后进行计算。如果要像示例中那样将其格式化为百分比字符串,则可以将计数传递给scales::percent
,例如,将0.75格式化为75%。然后,您可以将日期和计数旁边的列删除,或者在更复杂的情况下,您可能想要进行进一步的重塑。
df_complete %>%
spread(key = Type, value = Count) %>%
mutate(Count = (A - C) / (A + B + C)) %>%
mutate(Count = scales::percent(Count)) %>%
select(Date, Count)
#> # A tibble: 7 x 2
#> Date Count
#> <date> <chr>
#> 1 2018-11-01 67%
#> 2 2018-11-02 100%
#> 3 2018-11-03 100%
#> 4 2018-11-04 100%
#> 5 2018-11-05 100%
#> 6 2018-11-06 0%
#> 7 2018-11-07 100%
轻微的变化是使用rowwise
按每一行分组,这使您可以在类型列上调用sum
。
df_complete %>%
spread(key = Type, value = Count) %>%
rowwise() %>%
mutate(Count = (A - C) / sum(A, B, C)) %>%
mutate(Count = scales::percent(Count)) %>%
select(Date, Count)
#> Source: local data frame [7 x 2]
#> Groups: <by row>
#>
#> # A tibble: 7 x 2
#> Date Count
#> <date> <chr>
#> 1 2018-11-01 66.7%
#> 2 2018-11-02 100%
#> 3 2018-11-03 100%
#> 4 2018-11-04 100%
#> 5 2018-11-05 100%
#> 6 2018-11-06 0%
#> 7 2018-11-07 100%
由reprex package(v0.2.1)于2018-11-28创建