如何通过在R中保持一些变量的静态和动态来重构具有多个变量的数据帧



我在R.中使用以下数据帧

uid     Date                  batch_no       marking       seq
K-1     16/03/2020  12:11:33  7              S1            FRD
K-1     16/03/2020  12:11:33  7              S1            FHL
K-2     16/03/2020  12:11:33  8              SE_hold1      ABC
K-3     16/03/2020  12:11:33  9              SD_hold2      DEF
K-4     16/03/2020  12:11:33  8              S1            XYZ
K-5     16/03/2020  12:11:33                 NA            ABC
K-6     16/03/2020  12:11:33  7                            ZZZ
K-7     16/03/2020  12:11:33  NA             S2            NA
K-8     16/03/2020  12:11:33  6              S3            FRD
  • seq列将具有八个唯一值,包括NA;没有必要为每天的日期提供所有8个值
  • batch_no将具有六个唯一值,包括NA和空白;没有必要为每天的日期提供所有六个值
  • marking列将具有~25个唯一值,但需要将后缀为_hold#的值视为Hold;之后,将存在包括空白和NA在内的六个唯一值

要求按以下顺序合并dcast数据帧,以便为分析提供单个视图摘要。

我想在代码中保持所有唯一值的静态,这样,如果特定值在特定日期不可用,我将在摘要表中获得0或-。

期望输出:

seq      count  percentage   Marking     count     Percentage     batch_no   count    Percentage
FRD      1      12.50%       S1          2         25.00%         6          1        12.50%
FHL      1      12.50%       S2          1         12.50%         7          2        25.00%
ABC      2      25.00%       S3          1         12.50%         8          2        25.00%
DEF      1      12.50%       Hold        2         25.00%         9          1        12.50%
XYZ      1      12.50%       NA          1         12.50%         NA         1        12.50%
ZZZ      1      12.50%       (Blank)     1         12.50%         (Blank)    1        12.50%
FRD      1      12.50%         -         -           -             -         -           -
NA       1      12.50%         -         -           -             -         -           -
(Blank)  0      0.00%          -         -           -             -         -           -
Total    8      112.50%        -         8         100.00%         -         8         100.00%

对于seq,由于对值FRDFHL重复计数相同的uid,因此我们具有%>100。这是公认的情况。在CCD_ 14中将只有CCD_ 15的不同计数。

有几种方法可以解决这个问题,其中一种方法是从清理数据开始,将数据连接到一个具有您明确想要的所有组合的表中,然后进行汇总。注意:由于组合了这三列的组合,这将给出很多显式的0。

df = df_original %>% 
mutate(marking = if_else(str_detect(marking,"hold"),"Hold", marking)) %>% 
mutate_at(vars(c("seq", "batch_no", "marking")), forcats::fct_explicit_na, na_level = "(Blank)") 
## You need to do something similar with vectors of the possible values
## i.e. I don't know all the levels of your factors
#--------------------------------------------------------------------------
# Appending the NA and (Blank) levels ensures they are included in case the
# batch of data doesn't have them
df_seq = data.frame(seq = c(df$seq %>% levels(),"NA","(Blank)") %>% unique())
df_batch_no = data.frame(batch_no = c(df$batch_no %>% levels(),"NA","(Blank)") %>% unique())
df_marking = data.frame(marking = c(df$marking %>% levels(),"NA","(Blank)") %>% unique())
# would have been really nice to use janitor::tabyl but your output won't allow
df_seq_summary = df %>%
group_by(seq) %>% 
summarise(count = n()) %>% 
right_join(df_seq, by = "seq") %>% 
mutate(count = replace_na(count, 0),
percentage = count / n()) %>% 
mutate(row = row_number())
df_marking_summary =  df %>%
group_by(marking) %>% 
summarise(count = n()) %>% 
right_join(df_marking, by = "marking") %>% 
mutate(count = replace_na(count, 0),
percentage = count / sum(count)) %>% 
mutate(row = row_number())
df_batch_no_summary =  df %>%
group_by(batch_no) %>% 
summarise(count = n()) %>% 
right_join(df_batch_no, by = "batch_no") %>% 
mutate(count = replace_na(count, 0),
percentage = count / sum(count)) %>% 
mutate(row = row_number())
df = df_seq_summary %>% 
full_join(df_marking_summary, by =  "row", suffix = c("", "_marking")) %>% 
full_join(df_batch_no_summary, by =  "row", suffix = c("", "_batch_no")) %>% 
select(-row) %>% 
bind_rows(summarise_all(., ~(if(is.numeric(.)) sum(if_else(.>0,as.double(.),0), na.rm = T) else "Total"))) %>% 
mutate_at(vars(contains("percentage")), scales::percent, accuracy = 0.01)

最新更新