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

Sop*_*son 6 r dataframe dplyr

我在 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
Run Code Online (Sandbox Code Playgroud)
  • 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%
Run Code Online (Sandbox Code Playgroud)

因为seq我们有 % > 100 因为重复计算uidvalueFRDFHL. 这是公认的场景。InTotal将只有不同的uid.

MMe*_*rry 3

有几种方法可以解决这个问题,一种方法是从清理数据开始,将其连接到包含您明确想要的所有组合的表中,然后进行汇总。注意:由于组合了这三列的组合,这将给出很多显式的 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)
Run Code Online (Sandbox Code Playgroud)

  • 嘿索菲亚,我想了解这些业务需求,因为你故意违背正常的设计模式,我想确认这是你真正想要做的,而不是我的误解。即 - 你想要三个摘要连接在一起 - seq 列有 FRD 两次,但它们没有算在一起?- 您似乎想要非零计数?- 百分比是计数总和除以不同计数 (2认同)
  • 我明白,始终保留一些变量并不困难。您形成一个定义的最小列表和“left_join”,我想要澄清的是其他评论。我很快就会更新代码。 (2认同)