[英]R: Function to combine columns with identical data
在我之前的帖子(見上面的鏈接)中,我想知道如何組合具有相同數據的列並更改列名以反映范圍。 我從生產的 function 開始
我應用了同樣的 function
library(dplyr)
library(flextable)
library(stringr)
library(tidyverse)
Shop_fcn <- function(data){
data %>%
group_by(Day) %>%
mutate(N_nam = n_distinct(Names)) %>%
group_by(Names, Day, N_nam, Store, Item) %>%
summarize(n_item = n()) %>%
group_by(Day, N_nam, Store, Item) %>%
summarize(n_nam = n(),
n_item = sum(n_item))%>%
mutate(pct = round(n_nam/N_nam*100,digits = 1),
txt = paste0( n_nam, " (", pct, "%)"),
Day_n = (paste0("Day ", Day," (N=", N_nam, ")")))%>%
ungroup %>%
select(Day_n , Store, Item, txt) %>%
group_by(Store, Item, txt) %>%
summarise(Day_n = if(n() > 1)
sprintf('Day %s %s', paste(range(readr::parse_number(unique(Day_n))),
collapse=' - '),
str_remove(first(Day_n), '^[^(]+')) else Day_n) %>%
pivot_wider(values_from = txt, names_from = Day_n) %>%
mutate_at(vars(starts_with(c("Day"))), ~if_else(is.na(.), "", .)) %>%
arrange(Store, Item) %>%
group_by(store2 = Store) %>%
mutate(Store = if_else(row_number() != 1, "", Store))%>%
ungroup() %>%
select(Store, Item, str_sort(names(.)[-(1:2)], numeric = TRUE), -store2)
}
到更大的數據集
Names <- as.character(c('Adam','Morticia','Morticia','Morticia','Morticia','Morticia','Morticia','Morticia',
'Morticia','Morticia','Morticia','Morticia','Mickey','Minnie','Minnie','Minnie','Minnie','Minnie',
'Lucy', 'Lucy','Lucy','Morticia','Morticia','Morticia','Adam','Gomez','Olive','Olive','Olive',
'Ricky','Morticia','Adam','Eve','Ricky','Morticia','Morticia','Minnie','Adam','Lucy','Ricky',
'Ricky','Ricky','Ricky','Ricky','Minnie','Adam','Adam', 'Morticia', 'Adam', 'Adam', 'Adam', 'Adam',
'Adam','Lucy','Olive','Eve','Gomez','Morticia','Mickey','Olive'))
Day <- as.numeric(c(1,1,2,3,6,8,9,10,11,12,13,14,1,1,2,5,6,14,1,1,14,4,4,4,2,1,1,1,14,1,5,2,
1,1,4,5,3,2,1,1,14,14,14,14,4,2,2,4,2,2,2,2,14,1,1,14,14,7,14,1))
Store <- as.character(c('None','None','None','None','None','None','None','None','None','None',
'None','None','None','None','None','None','None','None','ACE','ACE','ACE','ACE','Amazon','Amazon',
'Best Buy','CVS','Hobby Lobby','Hobby Lobby','Hobby Lobby','Home Depot','Home Depot',
'Ikea','Ikea','Ikea','Ikea','Ikea','Ikea','Lowes','Lowes','Petco','Petco','Petco','Petco',
'Petco','Petco','Target','Target','Target','Walgreens','Walgreens','Walgreens','Walgreens',
'Walgreens','Walgreens','Walgreens','Walmart','Walgreens','Walgreens','Walgreens','Walgreens'))
Item <- as.character(c('None','None','None','None','None','None','None','None','None','None','None','None',
'None','None', 'None','None','None','None', 'Hammer','Nails','Plywood', 'Bricks','Frame','Batteries','TV','Advil',
'Brush','Paint','Paint','Level','Wrench','Pillow', 'Blanket','Lamp','Vase','Table','Chair','Screwdriver','Plunger','Cat food',
'Cat litter','Goldfish','Dog food','Dog treat','Hamster','Rug','Vacuum',
'Gloves','Tylenol','Napkins','Benadryl','Soap','Soap','Shampoo','Conditioner','Lotion',
'Lotion','Foil','Lotion','Foil'))
Shop_list <- as.data.frame(cbind(Names, Day, Store, Item), stringsAsFactors=FALSE)
Shop_day<- Shop_list %>%
bind_rows() %>%
Shop_fcn ()
flextable(Shop_day)
第 1-14 天和第 3-5 天不應合並
應用我原來的 function 讓我更接近我想要的 output,
Shop_fcn <- function(data){
data %>%
group_by(Day) %>%
mutate(N_nam = n_distinct(Names)) %>%
group_by(Names, Day, N_nam, Store, Item) %>%
summarize(n_item = n()) %>%
group_by(Day, N_nam, Store, Item) %>%
summarize(n_nam = n(),
n_item = sum(n_item))%>%
mutate(pct = round(n_nam/N_nam*100,digits = 1),
txt = paste0( n_nam, " (", pct, "%)"),
Day_n = (paste0("Day ", Day," (N=", N_nam, ")")))%>%
ungroup %>% select(Day_n , Store, Item, txt) %>%
pivot_wider(values_from = txt, names_from = Day_n) %>%
mutate_at(vars(starts_with(c("Day"))), ~if_else(is.na(.), "", .)) %>%
arrange(Store, Item) %>%
group_by(store2 = Store) %>%
mutate(Store = if_else(row_number() != 1, "", Store))%>%
ungroup() %>% select(-store2)
}
Shop_day<- Shop_list %>%
bind_rows() %>%
Shop_fcn ()
flextable(Shop_day)
但是,我現在遇到了相同的問題,即合並相同的日期(特別是第 8-13 天)和新一期未訂購 1-14 天的新問題。
我不確定最好的解決方案是修改 function,還是將新的 function 應用於 flextable 以組合列和相應的列名。
我試圖刪除重復的列,但仍然無法想出一個解決方案來解決如何將重復列的名稱保留為一個范圍或如何以正確的順序獲取列。
Shop_nodup <- Shop_day[!duplicated(as.list(Shop_day))]
flextable(Shop_nodup)
列名不按順序排列的原因是因為Day
列是字符類型而不是數字類型。 將其轉換為數字 class 將使它們按所需順序排列。 數字變成字符,因為在您的數據生成代碼中,您使用as.data.frame(cbind(....))
其中cbind
將數據轉換為矩陣,並且由於矩陣可以包含只有類型的數據,它會將數字轉換為字符。 相反,您應該使用data.frame(....)
來保持類的類型不變。
要將日期列與相似的值組合在一起,我在從每天的值創建唯一鍵后使用rleid
。
您可以使用的 function 是 -
library(tidyverse)
library(data.table)
library(flextable)
Shop_fcn <- function(data){
Shop_list %>%
group_by(Day = as.numeric(Day)) %>%
mutate(N_nam = n_distinct(Names)) %>%
group_by(Names, Day, N_nam, Store, Item) %>%
summarize(n_item = n()) %>%
group_by(Day, N_nam, Store, Item) %>%
summarize(n_nam = n(),
n_item = sum(n_item)) %>%
ungroup -> tmp
tmp %>%
group_by(Day) %>%
summarise(txt = paste(n_nam, n_item, Store, Item, sep = '-', collapse = ',')) %>%
mutate(grp = rleid(txt)) %>%
select(-txt) %>%
left_join(tmp, by = 'Day') %>%
group_by(grp) %>%
mutate(pct = round(n_nam/N_nam*100,digits = 1),
txt = paste0( n_nam, " (", pct, "%)"),
Day_n = if(n_distinct(Day) > 1) sprintf('Day %s - %s (N = %s)', first(Day), last(Day), N_nam) else sprintf('Day %s (N=%s)', Day, N_nam)) %>%
ungroup %>%
select(Day_n, Store, Item, txt) %>%
pivot_wider(values_from = txt, names_from = Day_n, values_fn = first, values_fill = '') %>%
arrange(Store, Item) %>%
group_by(Store) %>%
mutate(Store = if_else(row_number() != 1, "", Store)) %>%
ungroup()
}
對於您上一篇文章中的數據,這將返回 -
Shop_day<- Shop_list %>% Shop_fcn
flextable(Shop_day)
對於這篇文章中的數據,它返回 -
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.