[英]dplyr function with optional grouping only when argument provided
我需要編寫一個dplyr函數來創建自定義區域圖。 所以這是我的嘗試。
area_plot <- function(data, what, by){
by <- ensym(by)
what <- ensym(what)
data %>%
filter(!is.na(!!by)) %>%
group_by(date, !!by) %>%
summarise(!!what := sum(!!what, na.rm = TRUE)) %>%
complete(date, !!by, fill = rlang::list2(!!what := 0)) %>%
ggplot(aes(date, !!what, fill = !!by)) +
geom_area(position = 'stack') +
scale_x_date(breaks = '1 month', date_labels = '%Y-%m', expand = c(.01, .01)) +
theme_minimal() +
theme(axis.text.x = element_text(angle = 90, vjust = .4)) +
labs(fill = '')
}
但是,我一直在想,如果有任何默認值by
論點,將輸出geom_area
所有組一起陰謀。 我知道我可以先使用if
來定義ggplot2
使用的數據,並在函數中執行類似的操作:
if (by != 'default') {
data <- data %>%
filter(!is.na(!!by)) %>%
group_by(date, !!by) %>%
summarise(!!what := sum(!!what, na.rm = TRUE)) %>%
complete(date, !!by, fill = rlang::list2(!!what := 0))}
ggplot(data, aes(date, !!what, fill = !!by)) +
geom_area(position = 'stack') +
scale_x_date(breaks = '1 month', date_labels = '%Y-%m', expand = c(.01, .01)) +
theme_minimal() +
theme(axis.text.x = element_text(angle = 90, vjust = .4)) +
labs(fill = '')
但是我思考是否有一個巧妙的技巧來為group_by
提供一些值(例如,常量),這會使得summarise
保留原始結構(所以基本上什么都不做)盡管被調用了。 類似於在ggplot2
為某些美學提供常量時的行為。
請參閱所附數據的樣本。 group
是一個可選的分組變量。
structure(list(date = structure(c(17052, 17654, 17111, 17402,
17090, 17765, 17181, 17301, 17496, 17051, 16980, 17155, 17599,
16986, 17607, 17620, 17328, 17085, 17666, 17759, 17238, 16975,
17242, 17322, 17625, 17598, 17124, 17648, 17675, 17613, 17044,
16984, 16968, 17421, 17152, 17148, 17418, 17017, 17655, 17148,
16981, 17644, 17149, 17090, 17548, 17474, 17564, 17530, 17237,
17679, 17166, 17470, 17427, 17306, 17677, 17600, 17458, 17697,
17602, 16990, 17111, 17150, 17561, 17406, 17135, 17181, 17014,
17419, 17273, 17416, 17101, 17367, 17170, 17015, 17386, 17444,
17507, 17592, 17058, 17292, 16966, 17756, 17239, 17479, 17260,
17477, 16989, 17032, 17219, 17430, 17696, 17487, 17578, 17759,
17269, 17634, 17279, 17478, 17222, 17296), class = "Date"), count = c(2,
4, 2, 3, 6, 1, 4, 8, 1, 5, 1, 5, 1, 1, 2, 6, 3, 5, 2, 7, 3, 4,
1, 3, 4, 2, 4, 1, 2, 3, 16, 1, 5, 4, 3, 4, 4, 6, 1, 3, 3, 1,
3, 10, 5, 1, 4, 2, 2, 4, 5, 26, 4, 9, 3, 1, 3, 1, 4, 1, 2, 3,
1, 13, 3, 1, 3, 1, 1, 3, 1, 3, 3, 4, 1, 2, 2, 3, 1, 9, 3, 1,
2, 1, 4, 2, 1, 2, 4, 3, 2, 3, 1, 6, 5, 1, 2, 2, 3, 4), group = c("NON-FOOD",
NA, NA, NA, NA, "MIX", NA, NA, "MIX", NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA, "FOOD", NA, "FOOD", NA, NA, "MIX",
NA, NA, NA, "FOOD", "FOOD", NA, NA, NA, NA, "FOOD", NA, NA, "FOOD",
NA, NA, NA, "FOOD", NA, NA, NA, NA, NA, NA, NA, NA, "MIX", NA,
NA, "FOOD", NA, "FOOD", NA, NA, "FOOD", NA, "FOOD", NA, NA, "NON-FOOD",
NA, NA, "MIX", "NON-FOOD", NA, NA, NA, NA, NA, NA, "IMAGE", NA,
"FOOD", NA, NA, NA, "FOOD", NA, "FOOD", NA, NA, NA, NA, NA, NA,
NA, NA, "FOOD", "FOOD", NA, NA, NA)), row.names = c(73008L, 535553L,
122359L, 321655L, 105632L, 646925L, 172409L, 256204L, 394666L,
72385L, 20180L, 156162L, 478525L, 91409L, 485397L, 501386L, 277336L,
100902L, 549629L, 640676L, 209400L, 16603L, 224543L, 272638L,
505291L, 475497L, 131845L, 529041L, 558295L, 491746L, 67156L,
23499L, 11150L, 334454L, 154958L, 150674L, 333348L, 45599L, 536064L,
150673L, 20668L, 524095L, 151809L, 105713L, 433853L, 375687L,
445626L, 420587L, 208594L, 562514L, 162403L, 372594L, 338509L,
259784L, 560356L, 480072L, 361471L, 579474L, 481262L, 26469L,
122119L, 152537L, 443426L, 325045L, 140531L, 171908L, 43547L,
333968L, 237152L, 332106L, 114754L, 298081L, 164923L, 43577L,
311250L, 350267L, 404348L, 470188L, 78329L, 250086L, 9486L, 638289L,
209638L, 379370L, 227299L, 377487L, 26333L, 55058L, 195261L,
340666L, 578515L, 387600L, 457752L, 640729L, 235389L, 514348L,
240303L, 378836L, 197409L, 252746L), class = "data.frame")
這是執行函數前幾個步驟的一種方法(我沒有進入所有ggplot
東西,只是如何進行分組)。 通常,要設置默認的“不執行任何操作”操作(例如默認為不分組),您將在函數中使用argument = NULL
- 您可以查看其他函數的doc頁面以了解如何完成此操作。 這是關於NA
和NULL
之間差異的SO帖子 。
我不是非常擅長使用quosures,但是我已經構建了一些函數並且經常依賴於一些rlang
/ tidyselect
輔助函數,例如我在這里使用的rlang::quo_is_null
。 其他人也許可以在沒有助手的情況下重寫這個。
首先要看到您正在尋找的行為,作為分組或未分組的摘要:
library(tidyverse)
# grouped
df %>%
filter(!is.na(group)) %>%
group_by(group) %>%
summarise(count = sum(count, na.rm = TRUE))
#> # A tibble: 4 x 2
#> group count
#> <chr> <dbl>
#> 1 FOOD 34
#> 2 IMAGE 1
#> 3 MIX 8
#> 4 NON-FOOD 6
# not grouped
df %>%
# add in if you want to filter ungrouped data
summarise(count = sum(count, na.rm = TRUE))
#> count
#> 1 347
然后在函數中,我創建了what_var
作為what
的quosure版本(rlang專家,隨意在這個術語上糾正我......?)。 我通常會將_var
添加到名稱中以跟蹤原始參數的內容以及已經enquo
。 請檢查參數是否by
是通過創建一個quosure空by
,並檢查是否是空。 如果它不為null,即如果某個列名是由forcut提供by
,則過濾和分組。 如果為null,則只傳遞原始數據幀。 我將數據傳遞給else
語句中的新變量,以避免在原始數據幀上運行。 然后,無論數據是否分組,總結what
。
to_group_or_not_to_group <- function(data, what, by = NULL) {
what_var <- enquo(what)
if(!rlang::quo_is_null(enquo(by))) {
by_var <- enquo(by)
grouped_or_not <- data %>%
filter(!is.na(!!by_var)) %>%
group_by(!!by_var)
} else {
grouped_or_not <- data
}
grouped_or_not %>%
summarise(!!quo_name(what_var) := sum(!!what_var, na.rm = TRUE))
}
驗證您是否獲得了目標結果。 使用分組變量:
df %>%
to_group_or_not_to_group(what = count, by = group)
#> # A tibble: 4 x 2
#> group count
#> <chr> <dbl>
#> 1 FOOD 34
#> 2 IMAGE 1
#> 3 MIX 8
#> 4 NON-FOOD 6
提供NULL
作為(缺少)分組變量:
df %>%
to_group_or_not_to_group(what = count, by = NULL)
#> count
#> 1 347
如果沒有分組變量,則返回默認值by = NULL
:
df %>%
to_group_or_not_to_group(what = count)
#> count
#> 1 347
由reprex包創建於2018-10-16(v0.2.1)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.