Подводя итоги используя dplyr с циклом for - PullRequest
2 голосов
/ 03 ноября 2019

Я хотел бы суммировать каждую из моих независимых переменных (столбцов) с моей целевой переменной, используя dplyr над циклом for. Это мой основной фрейм данных:

contract_ID    Asurion         Variable_1     Variable_2  Variable_3
         1          Y                a               c          f
         2          Y                a               d          g
         3          N                b               c          g
         4          N                a               d          f
         5          Y                b               c          f
         6          Y                a               d          f

После того, как я получу группу, я получу

a1 <- a %>% 
  group_by(Asurion,BhvrBnk_Donates_to_Env_Causes) %>%       
  summarise(counT=n_distinct(CONTRACT_ID)) %>%                                        
  mutate(perc=paste0(round(counT/sum(counT)*100,2),"%"))

 Asurion Variable_1 CounT   perc
    Y         a        3     75%
    Y         b        1     25%
    N         a        1     50%
    N         b        1     50%

. Я бы хотел, чтобы это резюме для каждой моей переменной присутствовало в моем фрейме данных, и я бы хотелсделать это с помощью цикла for. Как мне получить желаемый результат

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

categorical <- colnames(a)###where categroical is the names of all columns in a  
###I would like to have a for loop for every column in a and summarise in the following way. I would like to store each of the summarisations in a separate dataframe 

for (i in categorical) {
  a[[i]] <- a %>% 
     group_by(Asurion,get(i)) %>% 
    summarise(counT=n_distinct(CONTRACT_ID)) %>% 
    mutate(perc=paste0(round(counT/sum(counT)*100,2),"%"))
  }

Ответы [ 3 ]

2 голосов
/ 03 ноября 2019

Возможно, вам не нужно for loop, чтобы получить то, что вы хотели.

df<-data.frame(contract_ID = 1:6, 
               Asurion = c("Y", "Y", "N", "N", "Y", "Y"), 
               Variable_1 = c("a", "a", "b", "a", "b","a"), 
               Variable_2 = c("c", "d", "c", "d", "c", "d"), 
               Variable_3 = c("f", "g", "g", "f", "f", "f"))

pct <- function(x) {
  df %>% 
  group_by(Asurion, {{x}}) %>% 
  summarise(counT=n_distinct(contract_ID)) %>% 
  mutate(perc = paste0(round(counT/sum(counT)*100,2),"%"))
}

pct(Variable_1)
pct(Variable_2)
pct(Variable_3)

Если у вас много переменных, вы можете использовать что-то вроде for loop или apply для итерации последнего бита. Вот один из вариантов:

categorical<- df[3:5]
a <- list()
j = 1
for (i in categorical) {
  a[[j]] <- df %>% 
    group_by(Asurion, {{i}}) %>% 
    summarise(counT=n_distinct(contract_ID)) %>% 
    mutate(perc = paste0(round(counT/sum(counT)*100,2),"%"))
  j = j + 1
}
a
[[1]]
# A tibble: 4 x 4
# Groups:   Asurion [2]
  Asurion `<fct>` counT perc 
  <fct>   <fct>   <int> <chr>
1 N       a           1 50%  
2 N       b           1 50%  
3 Y       a           3 75%  
4 Y       b           1 25%  

[[2]]
# A tibble: 4 x 4
# Groups:   Asurion [2]
  Asurion `<fct>` counT perc 
  <fct>   <fct>   <int> <chr>
1 N       c           1 50%  
2 N       d           1 50%  
3 Y       c           2 50%  
4 Y       d           2 50%  

[[3]]
# A tibble: 4 x 4
# Groups:   Asurion [2]
  Asurion `<fct>` counT perc 
  <fct>   <fct>   <int> <chr>
1 N       f           1 50%  
2 N       g           1 50%  
3 Y       f           3 75%  
4 Y       g           1 25%  

РЕДАКТИРОВАТЬ Добавить имена переменных в качестве новых значений переменных в ответ на ваш вопрос для определения group_by переменных.

categorical<- df[3:5]
vnames <- colnames(categorical)
a <- list()
j = 1
for (i in categorical) {
  a[[j]] <- df %>% 
    group_by(Asurion, {{i}}) %>% 
    summarise(counT=n_distinct(contract_ID)) %>% 
    mutate(perc = paste0(round(counT/sum(counT)*100,2),"%"))
    a[[j]]$vnames = vnames[j]
  j = j + 1
}
a
1 голос
/ 03 ноября 2019

Вот способ и , который создает список результатов по вашему вопросу:

library(tidyr)
library(dplyr)

DF%>%
  add_count(Asurion, name = 'all_n')%>%
  pivot_longer(cols = starts_with('Variable'))%>%
  group_by(Asurion, name, value)%>%
  summarize(CounT = n(), 
            perc = n() / first(all_n))%>%
  ungroup()%>%
  group_split(name, keep = F)

[[1]]
# A tibble: 4 x 4
  Asurion value CounT  perc
  <fct>   <fct> <int> <dbl>
1 N       a         1  0.5 
2 N       b         1  0.5 
3 Y       a         3  0.75
4 Y       b         1  0.25

[[2]]
# A tibble: 4 x 4
  Asurion value CounT  perc
  <fct>   <fct> <int> <dbl>
1 N       c         1   0.5
2 N       d         1   0.5
3 Y       c         2   0.5
4 Y       d         2   0.5

[[3]]
# A tibble: 4 x 4
  Asurion value CounT  perc
  <fct>   <fct> <int> <dbl>
1 N       f         1  0.5 
2 N       g         1  0.5 
3 Y       f         3  0.75
4 Y       g         1  0.25

И базовое решение, которое лучше соответствуетпредполагаемый результат:

## base
lapply(grep('Variable', names(DF), value = T), # get vars starting with "Variable"
       function(col_name){
         t = table(DF[, c('Asurion', col_name)]) 
         data.frame(prop.table(t, 1), CounT = c(t))
       }
)

[[1]]
  Asurion Variable_1 Freq CounT
1       N          a 0.50     1
2       Y          a 0.75     3
3       N          b 0.50     1
4       Y          b 0.25     1

[[2]]
  Asurion Variable_2 Freq CounT
1       N          c  0.5     1
2       Y          c  0.5     2
3       N          d  0.5     1
4       Y          d  0.5     2

[[3]]
  Asurion Variable_3 Freq CounT
1       N          f 0.50     1
2       Y          f 0.75     3
3       N          g 0.50     1
4       Y          g 0.25     1

Данные на @Zhiqiang Wang:

DF<-data.frame(contract_ID = 1:6, 
               Asurion = c("Y", "Y", "N", "N", "Y", "Y"), 
               Variable_1 = c("a", "a", "b", "a", "b","a"), 
               Variable_2 = c("c", "d", "c", "d", "c", "d"), 
               Variable_3 = c("f", "g", "g", "f", "f", "f"))
1 голос
/ 03 ноября 2019

Base R Solution:

 df2 <- data.frame(

  reshape(df,

          direction = "long",

          varying = names(df)[!(names(df) %in% c("contract_ID", "Asurion"))],

          v.names = "Val",

          timevar = "Variable",

          times = names(df)[!(names(df) %in% c("contract_ID", "Asurion"))]

  ),

  row.names = NULL,

  stringsAsFactors = F

)

# Count the unique contract ids within the specified group: 

df2$CounT <- as.numeric(ave(df2$contract_ID,

                            paste(df2$Asurion, df2$Variable, df2$Val, sep = "_"),

                            FUN = function(x){length(unique(x))}))

# Create the percentage of total counts: 

df2$perc <- paste0(round((df2$CounT/as.numeric(ave(df2$Variable, 

                                                   paste(df2$Variable, df2$Val, sep = "_"),

                                                   FUN = length))) * 100,2),"%")

# Allocate some memory for list of dataframes: 

df_list <- vector("list", length(unique(df2$Variable)))

# Store the summary dataframes in the list: 

df_list <- lapply(split(df2, df2$Variable),

                  function(x){x <- unique(x[,c(!(names(x) %in% c("id", "contract_ID")))])})

# Push the dataframes from the list into the global environment: 

list2env(df_list, .GlobalEnv)

Tidyverse Solution:

require(tidyverse)

# Allocate some memory for list of dataframes: 

df_list <- vector("list", length(unique(names(df)[grepl("Variable_", names(df))])))

# Tidyverse summary: 

df_list <- 

  df %>% 

  gather(Variable, Value, -contract_ID, -Asurion) %>% 

  group_by(Asurion, Variable, Value) %>% 

  mutate(CounT = length(unique(contract_ID))) %>%

  ungroup() %>% 

  group_by(Variable, Value) %>% 

  mutate(perc = paste0(round((CounT/n()) * 100, 2), "%")) %>% 

  ungroup() %>% 

  select(-contract_ID) %>% 

  distinct() %>% 

  split(., .$Variable)

# Push the dataframes from the list into the global environment: 

list2env(df_list, .GlobalEnv)

Данные:

structure(list(contract_ID = 1:6, Asurion = c("Y", "Y", "N", 
"N", "Y", "Y"), Variable_1 = c("a", "a", "b", "a", "b", "a"), 
    Variable_2 = c("c", "d", "c", "d", "c", "d"), Variable_3 = c("f", 
    "g", "g", "f", "f", "f")), class = "data.frame", row.names = c(NA, 
-6L))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...