2
私はredditコメントでテキスト解析を行い、BigQuery内でTF-IDFを計算したいと思います。SQL(BigQuery)を使用してTF/IDFを計算するには
私はredditコメントでテキスト解析を行い、BigQuery内でTF-IDFを計算したいと思います。SQL(BigQuery)を使用してTF/IDFを計算するには
このクエリは、5つの段階で動作します:。
'
)の単語を正規化。それらの単語を配列に分割します。このクエリは、得られた値をチェーンの上に渡すことで、1回のパスでこれを行うことができます。
#standardSQL
WITH words_by_post AS (
SELECT CONCAT(link_id, '/', id) id, REGEXP_EXTRACT_ALL(
REGEXP_REPLACE(REGEXP_REPLACE(LOWER(body), '&', '&'), r'&[a-z]{2,4};', '*')
, r'[a-z]{2,20}\'?[a-z]+') words
, COUNT(*) OVER() docs_n
FROM `fh-bigquery.reddit_comments.2017_07`
WHERE body NOT IN ('[deleted]', '[removed]')
AND subreddit = 'movies'
AND score > 100
), words_tf AS (
SELECT id, word, COUNT(*)/ARRAY_LENGTH(ANY_VALUE(words)) tf, ARRAY_LENGTH(ANY_VALUE(words)) words_in_doc
, ANY_VALUE(docs_n) docs_n
FROM words_by_post, UNNEST(words) word
GROUP BY id, word
HAVING words_in_doc>30
), docs_idf AS (
SELECT tf.id, word, tf.tf, ARRAY_LENGTH(tfs) docs_with_word, LOG(docs_n/ARRAY_LENGTH(tfs)) idf
FROM (
SELECT word, ARRAY_AGG(STRUCT(tf, id, words_in_doc)) tfs, ANY_VALUE(docs_n) docs_n
FROM words_tf
GROUP BY 1
), UNNEST(tfs) tf
)
SELECT *, tf*idf tfidf
FROM docs_idf
WHERE docs_with_word > 1
ORDER BY tfidf DESC
LIMIT 1000
スタックオーバーフローのデータセットバージョン:前の回答対
#standardSQL
WITH words_by_post AS (
SELECT id, REGEXP_EXTRACT_ALL(
REGEXP_REPLACE(
REGEXP_REPLACE(
REGEXP_REPLACE(
LOWER(CONCAT(title, ' ', body))
, r'&', '&')
, r'&[a-z]*;', '')
, r'<[= \-:a-z0-9/\."]*>', '')
, r'[a-z]{2,20}\'?[a-z]+') words
, title, body
, COUNT(*) OVER() docs_n
FROM `bigquery-public-data.stackoverflow.posts_questions`
WHERE score >= 150
), words_tf AS (
SELECT id, words
, ARRAY(
SELECT AS STRUCT w word, COUNT(*)/ARRAY_LENGTH(words) tf
FROM UNNEST(words) a
JOIN (SELECT DISTINCT w FROM UNNEST(words) w) b
ON a=b.w
WHERE w NOT IN ('the', 'and', 'for', 'this', 'that', 'can', 'but')
GROUP BY word ORDER BY word
) tfs
, ARRAY_LENGTH((words)) words_in_doc
, docs_n
, title, body
FROM words_by_post
WHERE ARRAY_LENGTH(words)>20
), docs_idf AS (
SELECT *, LOG(docs_n/docs_with_word) idf
FROM (
SELECT id, word, tf.tf, COUNTIF(word IN UNNEST(words)) OVER(PARTITION BY word) docs_with_word, docs_n
, title, body
FROM words_tf, UNNEST(tfs) tf
)
)
SELECT id, ARRAY_AGG(STRUCT(word, tf*idf AS tf_idf, docs_with_word) ORDER BY tf*idf DESC) tfidfs
# , ANY_VALUE(title) title, ANY_VALUE(body) body # makes query slower
FROM docs_idf
WHERE docs_with_word > 1
GROUP BY 1
改良:一つ少ないGROUP BYデータセット全体では、より高速なクエリの実行を支援し、必要とされています。
私は間違っているかもしれませんが、どういうわけか、 'r '[az] {2,20} \'?[az] * ''ではなく' REGEXP_EXTRACT_ALL'で 'r' [az] {2、 20} \ '?[az] +' –
@MikhailBerlyantをチェックしていただきありがとうございます!違いは、単語が '' 'で終わることができるでしょうか? –
これはまさに私が思ったことです。コメントに「abc」のような言葉があります。o) –