Kha*_*hir 5 google-analytics r unnest dbplyr bigrquery
如果可能,我想bigrquery使用dplyr语法(而不是 SQL)探索 Google Analytics 360 数据。要点是我想了解用户旅程——我有兴趣在用户级别(甚至跨会话)找到最常见的页面序列。
我以为我可以这样做:
sample_query <- ga_sample %>%
select(fullVisitorId, date, visitStartTime, totals, channelGrouping,
hits.page.pagePath) %>%
collect()
Run Code Online (Sandbox Code Playgroud)
但我收到一个hits.page.pagePath未找到的错误。然后我尝试:
sample_query <- ga_sample %>%
select(fullVisitorId, date, visitStartTime, totals, channelGrouping, hits) %>%
collect() %>%
unnest_wider(hits)
Run Code Online (Sandbox Code Playgroud)
但结果是Error: Requested Resource Too Large to Return [responseTooLarge],这是完全有道理的。
从我收集到的信息来看,使用 SQL 语法,解决方法是unnest远程访问,并且select只有hits.page.pagePath字段(而不是整个hits顶级字段)。
例如,这样的事情(这是一个不同的查询,但传达了这一点):
SELECT
hits.page.pagePath
FROM
'bigquery-public-data.google_analytics_sample.ga_sessions_20160801' AS GA,
UNNEST(GA.hits) AS hits
GROUP BY
hits.page.pagePath
Run Code Online (Sandbox Code Playgroud)
是否可以用dplyr语法做类似的事情?如果不可能,那么使用 SQL 的最佳方法是什么?
谢谢!
更新:实际查询/代码
SELECT DISTINCT
fullVisitorId, visitId, date, visitStartTime, hits.page.pagePath, hits.time, geoNetwork.networkDomain
FROM 'bigquery-public-data.google_analytics_sample.ga_sessions_*' AS GA, UNNEST(GA.hits) AS hits
WHERE _TABLE_SUFFIX BETWEEN "20191101" AND "20191102"
AND geoNetwork.networkDomain NOT LIKE "%google%"
Run Code Online (Sandbox Code Playgroud)
从 R 转换为 BigQuery(或您使用的任何数据库语言)时可以创建的查询类型dbplyr取决于 R 和 BigQuery 之间定义的翻译。我找不到任何表明UNNEST在现有dbplyr包中定义翻译的示例。参考文献 1 ,参考文献 2
一种解决方法是定义一个自定义函数,不在 中进行翻译dbplyr,而是作为 旁边的翻译器dbplyr。以前,当我需要PIVOTSQL 但找不到tidyr::spread.
该方法有效,因为远程表由dbplyr两件事定义:(1) 到远程数据库的连接,(2) 返回表的当前视图的代码/查询。因此,一旦dbplyr将 R 转换为 BigQuery 或 SQL,它就会更新定义的后半部分。
我们可以使用自定义函数来做到这一点:
unnest <- function(input_tbl, select_columns, array_column, unnested_columns){
# extract connection
db_connection <- input_tbl$src$con
select_columns = paste0(select_columns, collapse = ", ")
unnested_columns = paste0(paste0("un.", unnested_columns), collapse = ", ")
# build SQL unnest query
sql_query <- dbplyr::build_sql(
con = db_connection
,"SELECT ", select_columns, ", ", position, ", ", unnested_columns, "\n"
,"FROM (\n"
,dbplyr::sql_render(input_tbl)
,"\n) AS src\n"
,"CROSS JOIN UNNEST(", array_column, ") AS un WITH OFFSET position"
)
return(dplyr::tbl(db_connection, dbplyr::sql(sql_query)))
}
Run Code Online (Sandbox Code Playgroud)
请注意,我是dbplyr用户,但不是 BigQuery 用户,所以上面我的语法可能不太完美。我已经关注了这个问题和这个问题的语法。
使用示例:
remote_table = tbl(bigquery_connection, from = "table_name")
unnested_table = unnest(remote_table, "ID", "array_col", "list")
# check syntax of dbplyr query
unnested_table %>% show_query()
# if this is not a valid bigquery query then next command will error
# view top 10 rows
unnested_table %>% head(10)
Run Code Online (Sandbox Code Playgroud)
如果remote_table看起来像:
ID ARRAY_COL
01 list = [a,b,c]
02 list = [d,e]
03 list = [q]
Run Code Online (Sandbox Code Playgroud)
那么unnested_table应该看起来像:
ID POSITION un.list
01 0 a
01 1 b
01 2 c
02 0 d
02 1 e
03 0 q
Run Code Online (Sandbox Code Playgroud)
并且unnested_table %>% show_query()应该看起来像这样:
<SQL>
SELECT *, position, un.list
FROM (
SELECT *
FROM table_name
) AS src
CROSS JOIN UNNEST(ARRAY_COL) AS un WITH OFFSET position
Run Code Online (Sandbox Code Playgroud)
我知道没有任何dbplyr功能可以_TABLE_SUFFIX BETWEEN "20191101" AND "20191102"轻松翻译,因此您必须以另一种方式处理这个问题 - 也许循环遍历 R 中的日期列表。
第一步是在dbplyr取消嵌套之前渲染查询。大概是这样的:
for(date in c("20191101", "20191102")){
table_name = paste0("bigquery-public-data.google_analytics_sample.ga_sessions_",date)
remote_table = tbl(bigquery_connection, from = table_name)
remote_table = remote_table %>%
filter(! (geoNetwork.networkDomain %like% "%google%")) %>%
select(fullVisitorId, visitId, date, visitStartTime, hits, geoNetwork.networkDomain) %>%
distinct()
}
Run Code Online (Sandbox Code Playgroud)
然后调用show_query(remote_table)应该产生与以下内容等效的内容。但它不会完全相同,因为dbplyr编写代码的方式与人类不同。
unnest <- function(input_tbl, select_columns, array_column, unnested_columns){
# extract connection
db_connection <- input_tbl$src$con
select_columns = paste0(select_columns, collapse = ", ")
unnested_columns = paste0(paste0("un.", unnested_columns), collapse = ", ")
# build SQL unnest query
sql_query <- dbplyr::build_sql(
con = db_connection
,"SELECT ", select_columns, ", ", position, ", ", unnested_columns, "\n"
,"FROM (\n"
,dbplyr::sql_render(input_tbl)
,"\n) AS src\n"
,"CROSS JOIN UNNEST(", array_column, ") AS un WITH OFFSET position"
)
return(dplyr::tbl(db_connection, dbplyr::sql(sql_query)))
}
Run Code Online (Sandbox Code Playgroud)
第二步是调用自定义的取消嵌套函数”
remote_table = unnest(remote_table,
select_columns = c("fullVisitorId", "visitId", "date", "visitStartTime", "geoNetwork.networkDomain"),
array_column = "hits",
unnested_columns = c("page.pagePath", "time")
)
Run Code Online (Sandbox Code Playgroud)
然后调用show_query(remote_table)应该产生以下结果:
remote_table = tbl(bigquery_connection, from = "table_name")
unnested_table = unnest(remote_table, "ID", "array_col", "list")
# check syntax of dbplyr query
unnested_table %>% show_query()
# if this is not a valid bigquery query then next command will error
# view top 10 rows
unnested_table %>% head(10)
Run Code Online (Sandbox Code Playgroud)
这可能是我所能提供的帮助,因为我自己没有一个 bigquery 环境来测试这一点。您可能需要调整自定义unnest函数以使其完全匹配您的上下文。希望以上内容足以帮助您入门。