具有 case_when 或 if_else 的 Dbplyr 计数唯一 (n_distinct)
Dbplyr count unique (n_distinct) with case_when or if_else
我想使用 dplyr::tbl
df 对象使用 dplyr::case_when
函数创建一个新列来计算唯一日期 (dplyr::n_distinct
)。
我尝试了以下代码:
df %>%
group_by(id) %>%
mutate(
last_date = max(date),
distinct_date_2020 = case_when(
date >= "2020-01-01" & date <= "2020-12-31" ~ n_distinct(date[!type == "Online"]),
TRUE ~ as.integer(0))
) %>%
ungroup()
distinct_date_2020
的mutate
不起作用。我收到以下错误消息:
[Microsoft][ODBC SQL Server Driver][SQL Server]Use of DISTINCT is not allowed with the OVER clause.
如果我 运行 没有 distinct_date_2020
,它会起作用:
df %>%
group_by(id) %>%
mutate(
last_date = max(date)
) %>%
ungroup()
我也尝试了这些变体,但没有成功:
distinct_date_2020 = n_distinct(date[date >= "2020-01-01" & date <= "2020-12-31" & !type == "Online"])
和
distinct_date_2020 = ifelse(date >= "2020-01-01" & date <= "2020-12-31", n_distinct(date[!type == "Online"]), NA)
如果我在 collect()
之后 运行 这些,它就可以工作。但我想将其作为 SQL 命令发送到服务器。
DBI::dbGetInfo
:
$dbms.name [1] "Microsoft SQL Server"
$db.version [1] "11.00.6523"
有人知道怎么解决吗?谢谢!
问题不在于 case_when
也不在于 n_distinct
,而是在于 date
.
的方括号
在 R 中,date[!type == "Online"]
选择列中所有行的子集。 SQL 查询(大部分)逐行工作,因此要求 n_distinct
的输入是根据类型列过滤日期列将不会产生有效的 SQL.
一种测试方法是使用 show_query
命令:
df %>%
group_by(id) %>%
mutate(
last_date = max(date),
distinct_date_2020 = case_when(
date >= "2020-01-01" & date <= "2020-12-31" ~ n_distinct(date[!type == "Online"]),
TRUE ~ as.integer(0))
) %>%
ungroup() %>%
show_query()
除非这生成有效的 SQL 代码,否则您的查询肯定会出错。
解决方案是单独进行过滤:
dist_dates = df %>%
group_by(id) %>%
filter(type != "Online",
date >= "2020-01-01",
date <= "2020-12-31") %>%
mutate(distinct_date_2020 = n_distinct(date)) %>%
ungroup()
max_dates = df %>%
group_by(id) %>%
mutate(last_date = max(date))
ungroup()
output = max_dates %>%
left_join(dist_dates, by = "id") %>%
select(id, last_date, distinct_date_2020)
我把两个总结分开做了,所以筛选不适用于last_date
。
我已经删除了 case_when
,因为在您的示例中它仅用作过滤器。但是如果你想这样做,试试:
dist_dates = df %>%
group_by(id) %>%
filter(type != "Online") %>%
mutate(
distinct_date_2020 = case_when(
date >= "2020-01-01" & date <= "2020-12-31" ~ n_distinct(date),
TRUE ~ as.integer(0))
) %>%
ungroup()
我终于让它工作了。我首先按 id
分组,提取最后日期,然后按年份分组(使用 DATEADD
和 DATEDIFF
,避免使用 lubridate
包,因为它与 dbplyr
包)。总结条件 [type != "Online"]
并将其放在括号之间也有效。我用下面的代码得到了想要的结果:
df %>%
group_by(id) %>%
mutate(
last_date_temp = max(date)
) %>%
group_by(year = DATEADD(sql("year"), DATEDIFF(sql("year"), 0, date), 0), id) %>%
summarize(
last_date = max(last_date_temp, na.rm = TRUE),
distinct_date = n_distinct(date[type != "Online"]),
) %>%
ungroup() %>%
select(id, year, everything()) %>%
arrange(id, year) %>%
collect()
我想使用 dplyr::tbl
df 对象使用 dplyr::case_when
函数创建一个新列来计算唯一日期 (dplyr::n_distinct
)。
我尝试了以下代码:
df %>%
group_by(id) %>%
mutate(
last_date = max(date),
distinct_date_2020 = case_when(
date >= "2020-01-01" & date <= "2020-12-31" ~ n_distinct(date[!type == "Online"]),
TRUE ~ as.integer(0))
) %>%
ungroup()
distinct_date_2020
的mutate
不起作用。我收到以下错误消息:
[Microsoft][ODBC SQL Server Driver][SQL Server]Use of DISTINCT is not allowed with the OVER clause.
如果我 运行 没有 distinct_date_2020
,它会起作用:
df %>%
group_by(id) %>%
mutate(
last_date = max(date)
) %>%
ungroup()
我也尝试了这些变体,但没有成功:
distinct_date_2020 = n_distinct(date[date >= "2020-01-01" & date <= "2020-12-31" & !type == "Online"])
和
distinct_date_2020 = ifelse(date >= "2020-01-01" & date <= "2020-12-31", n_distinct(date[!type == "Online"]), NA)
如果我在 collect()
之后 运行 这些,它就可以工作。但我想将其作为 SQL 命令发送到服务器。
DBI::dbGetInfo
:
$dbms.name [1] "Microsoft SQL Server"
$db.version [1] "11.00.6523"
有人知道怎么解决吗?谢谢!
问题不在于 case_when
也不在于 n_distinct
,而是在于 date
.
在 R 中,date[!type == "Online"]
选择列中所有行的子集。 SQL 查询(大部分)逐行工作,因此要求 n_distinct
的输入是根据类型列过滤日期列将不会产生有效的 SQL.
一种测试方法是使用 show_query
命令:
df %>%
group_by(id) %>%
mutate(
last_date = max(date),
distinct_date_2020 = case_when(
date >= "2020-01-01" & date <= "2020-12-31" ~ n_distinct(date[!type == "Online"]),
TRUE ~ as.integer(0))
) %>%
ungroup() %>%
show_query()
除非这生成有效的 SQL 代码,否则您的查询肯定会出错。
解决方案是单独进行过滤:
dist_dates = df %>%
group_by(id) %>%
filter(type != "Online",
date >= "2020-01-01",
date <= "2020-12-31") %>%
mutate(distinct_date_2020 = n_distinct(date)) %>%
ungroup()
max_dates = df %>%
group_by(id) %>%
mutate(last_date = max(date))
ungroup()
output = max_dates %>%
left_join(dist_dates, by = "id") %>%
select(id, last_date, distinct_date_2020)
我把两个总结分开做了,所以筛选不适用于last_date
。
我已经删除了 case_when
,因为在您的示例中它仅用作过滤器。但是如果你想这样做,试试:
dist_dates = df %>%
group_by(id) %>%
filter(type != "Online") %>%
mutate(
distinct_date_2020 = case_when(
date >= "2020-01-01" & date <= "2020-12-31" ~ n_distinct(date),
TRUE ~ as.integer(0))
) %>%
ungroup()
我终于让它工作了。我首先按 id
分组,提取最后日期,然后按年份分组(使用 DATEADD
和 DATEDIFF
,避免使用 lubridate
包,因为它与 dbplyr
包)。总结条件 [type != "Online"]
并将其放在括号之间也有效。我用下面的代码得到了想要的结果:
df %>%
group_by(id) %>%
mutate(
last_date_temp = max(date)
) %>%
group_by(year = DATEADD(sql("year"), DATEDIFF(sql("year"), 0, date), 0), id) %>%
summarize(
last_date = max(last_date_temp, na.rm = TRUE),
distinct_date = n_distinct(date[type != "Online"]),
) %>%
ungroup() %>%
select(id, year, everything()) %>%
arrange(id, year) %>%
collect()