Недавно я наткнулся на отличную статью, написанную Стианом Хаклевым, в которой он описывает то, что ему хотелось бы, чтобы ему сказали, прежде чем начинать с R , одна из которых заключается в том, чтобы очистить все данные в коде, который я решил попробовать.
Моя цель — оставить необработанные данные полностью неизменными и выполнить все преобразования в коде, которые можно запустить в любой момент.
Пока я пишу сценарии, я часто прыгаю, выборочно выполняя отдельные строки или блоки кода, выполняя команды для проверки данных в REPL (чтение-оценка-печать-цикл, где каждая команда выполняется, как только вы введите enter, на картинке выше это панель справа) и т. д.
Но я стараюсь убедиться, что когда я закончу, скрипт сам по себе будет работать.
Я думал, что набор данных Google Trends будет интересным, чтобы поиграть с ним, поскольку он дает вам CSV, содержащий несколько разных битов данных, которые меня интересуют только «интерес с течением времени».
Не очень легко автоматизировать загрузку CSV-файла, поэтому я сделал это вручную и автоматизировал все с этого момента.
Первым шагом было чтение файла CSV и изучение некоторых строк, чтобы увидеть, что в нем содержится:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
> library(dplyr) > googleTrends = read.csv("/Users/markneedham/Downloads/report.csv", row.names=NULL) > googleTrends %>% head()## row.names Web.Search.interest..neo4j## 1 Worldwide; 2004 - present ## 2 Interest over time ## 3 Week neo4j## 4 2004-01-04 - 2004-01-10 0## 5 2004-01-11 - 2004-01-17 0## 6 2004-01-18 - 2004-01-24 0 > googleTrends %>% sample_n(10)## row.names Web.Search.interest..neo4j## 109 2006-01-08 - 2006-01-14 0## 113 2006-02-05 - 2006-02-11 0## 267 2009-01-18 - 2009-01-24 0## 199 2007-09-30 - 2007-10-06 0## 522 2013-12-08 - 2013-12-14 88## 265 2009-01-04 - 2009-01-10 0## 285 2009-05-24 - 2009-05-30 0## 318 2010-01-10 - 2010-01-16 0## 495 2013-06-02 - 2013-06-08 79## 28 2004-06-20 - 2004-06-26 0 > googleTrends %>% tail()## row.names Web.Search.interest..neo4j## 658 neo4j example Breakout## 659 neo4j graph database Breakout## 660 neo4j java Breakout## 661 neo4j node Breakout## 662 neo4j rest Breakout## 663 neo4j tutorial Breakout |
Мы хотим сохранить только те строки, которые содержат (неделя, проценты) пары, поэтому первое, что мы сделаем, это переименуем столбцы:
|
1
|
names(googleTrends) = c("week", "score") |
Теперь мы хотим удалить строки, которые не содержат пар (неделя, процент). Самый простой способ сделать это — найти строки, которые не содержат значений даты в столбце «неделя».
Сначала нам нужно разделить даты начала и окончания в этом столбце с помощью функции strsplit .
Я обнаружил, что гораздо проще применить функцию к каждой строке отдельно, чем передавать список значений, поэтому я создал фиктивный столбец с номером строки, чтобы я мог это сделать (уловка, которую показал мне Антониос ):
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
> googleTrends %>% mutate(ind = row_number()) %>% group_by(ind) %>% mutate(dates = strsplit(week, " - "), start = dates[[1]][1] %>% strptime("%Y-%m-%d") %>% as.character(), end = dates[[1]][2] %>% strptime("%Y-%m-%d") %>% as.character()) %>% head()## Source: local data frame [6 x 6]## Groups: ind## ## week score ind dates start end## 1 Worldwide; 2004 - present 1 1 <chr[2]> NA NA## 2 Interest over time 1 2 <chr[1]> NA NA## 3 Week 90 3 <chr[1]> NA NA## 4 2004-01-04 - 2004-01-10 3 4 <chr[2]> 2004-01-04 2004-01-10## 5 2004-01-11 - 2004-01-17 3 5 <chr[2]> 2004-01-11 2004-01-17## 6 2004-01-18 - 2004-01-24 3 6 <chr[2]> 2004-01-18 2004-01-24 |
Теперь нам нужно избавиться от строк, которые имеют значение NA для «start» или «end»:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
|
> googleTrends %>% mutate(ind = row_number()) %>% group_by(ind) %>% mutate(dates = strsplit(week, " - "), start = dates[[1]][1] %>% strptime("%Y-%m-%d") %>% as.character(), end = dates[[1]][2] %>% strptime("%Y-%m-%d") %>% as.character()) %>% filter(!is.na(start) | !is.na(end)) %>% head()## Source: local data frame [6 x 6]## Groups: ind## ## week score ind dates start end## 1 2004-01-04 - 2004-01-10 3 4 <chr[2]> 2004-01-04 2004-01-10## 2 2004-01-11 - 2004-01-17 3 5 <chr[2]> 2004-01-11 2004-01-17## 3 2004-01-18 - 2004-01-24 3 6 <chr[2]> 2004-01-18 2004-01-24## 4 2004-01-25 - 2004-01-31 3 7 <chr[2]> 2004-01-25 2004-01-31## 5 2004-02-01 - 2004-02-07 3 8 <chr[2]> 2004-02-01 2004-02-07## 6 2004-02-08 - 2004-02-14 3 9 <chr[2]> 2004-02-08 2004-02-14 |
Далее мы избавимся от «недели», «инд» и «даты», так как они нам больше не понадобятся:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
> cleanGoogleTrends = googleTrends %>% mutate(ind = row_number()) %>% group_by(ind) %>% mutate(dates = strsplit(week, " - "), start = dates[[1]][1] %>% strptime("%Y-%m-%d") %>% as.character(), end = dates[[1]][2] %>% strptime("%Y-%m-%d") %>% as.character()) %>% filter(!is.na(start) | !is.na(end)) %>% ungroup() %>% select(-c(ind, dates, week)) > cleanGoogleTrends %>% head()## Source: local data frame [6 x 3]## ## score start end## 1 3 2004-01-04 2004-01-10## 2 3 2004-01-11 2004-01-17## 3 3 2004-01-18 2004-01-24## 4 3 2004-01-25 2004-01-31## 5 3 2004-02-01 2004-02-07## 6 3 2004-02-08 2004-02-14 > cleanGoogleTrends %>% sample_n(10)## Source: local data frame [10 x 3]## ## score start end## 1 8 2010-09-26 2010-10-02## 2 73 2013-11-17 2013-11-23## 3 52 2012-07-01 2012-07-07## 4 3 2005-06-19 2005-06-25## 5 3 2004-12-12 2004-12-18## 6 3 2009-09-06 2009-09-12## 7 71 2014-09-14 2014-09-20## 8 3 2004-12-26 2005-01-01## 9 62 2013-03-03 2013-03-09## 10 3 2006-03-19 2006-03-25 > cleanGoogleTrends %>% tail()## Source: local data frame [6 x 3]## ## score start end## 1 80 2014-10-19 2014-10-25## 2 80 2014-10-26 2014-11-01## 3 84 2014-11-02 2014-11-08## 4 81 2014-11-09 2014-11-15## 5 83 2014-11-16 2014-11-22## 6 2 2014-11-23 2014-11-29 |
Хорошо, теперь мы готовы к сюжету. Это была моя первая попытка:
|
1
2
3
4
|
> library(ggplot2)> ggplot(aes(x = start, y = score), data = cleanGoogleTrends) + geom_line(size = 0.5)## geom_path: Each group consist of only one observation. Do you need to adjust the group aesthetic? |
Как видите, не слишком удачно! Первая ошибка, которую я сделал, не говорит ggplot, что столбец ‘start’ является датой, и поэтому он может использовать этот порядок при построении графика:
|
1
2
3
|
> cleanGoogleTrends = cleanGoogleTrends %>% mutate(start = as.Date(start))> ggplot(aes(x = start, y = score), data = cleanGoogleTrends) + geom_line(size = 0.5) |
Моя следующая ошибка заключается в том, что «оценка» не рассматривается как непрерывная переменная, и поэтому мы получаем очень странную диаграмму. Мы можем видеть это, если мы вызываем функцию класса :
|
1
2
|
> class(cleanGoogleTrends$score)## [1] "factor" |
Давайте исправим это и построим график снова:
|
1
2
3
|
> cleanGoogleTrends = cleanGoogleTrends %>% mutate(score = as.numeric(score))> ggplot(aes(x = start, y = score), data = cleanGoogleTrends) + geom_line(size = 0.5) |
Это намного лучше, но в баллах по неделям довольно много шума, который мы можем немного сгладить, построив вместо этого скользящее среднее за последние 4 недели :
|
1
2
3
4
5
6
7
|
> library(zoo)> cleanGoogleTrends = cleanGoogleTrends %>% mutate(rolling = rollmean(score, 4, fill = NA, align=c("right")), start = as.Date(start)) > ggplot(aes(x = start, y = rolling), data = cleanGoogleTrends) + geom_line(size = 0.5) |
Вот полный код, если вы хотите воспроизвести:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
|
library(dplyr)library(zoo)library(ggplot2) googleTrends = read.csv("/Users/markneedham/Downloads/report.csv", row.names=NULL)names(googleTrends) = c("week", "score") cleanGoogleTrends = googleTrends %>% mutate(ind = row_number()) %>% group_by(ind) %>% mutate(dates = strsplit(week, " - "), start = dates[[1]][1] %>% strptime("%Y-%m-%d") %>% as.character(), end = dates[[1]][2] %>% strptime("%Y-%m-%d") %>% as.character()) %>% filter(!is.na(start) | !is.na(end)) %>% ungroup() %>% select(-c(ind, dates, week)) %>% mutate(start = as.Date(start), score = as.numeric(score), rolling = rollmean(score, 4, fill = NA, align=c("right"))) ggplot(aes(x = start, y = rolling), data = cleanGoogleTrends) + geom_line(size = 0.5) |
Мой следующий шаг — сопоставить оценки Google Trends с моим набором данных о встречах, чтобы увидеть, есть ли какие-нибудь интересные корреляции.
Кроме того, я использовал knitr при составлении этого поста — он отлично работает для проверки того, что вы включили все шаги и что он действительно работает!
| Ссылка: | Р: Очистка и отображение данных Google Trends от нашего партнера по JCG Марка Нидхэма в блоге Марка Нидхэма . |



