Получение данных с Yandex в R

Обратились ко мне с вопросом, как получить данные для обработки в R, например, для выявления зависимости курса валюты от прочих рыночных котировок. Если мы перейдет на страницу новостей Яндекса, то увидим графики и табличные данные, хотелось бы их как-то получить. Опишу пошагово как я решал эту задачу.

Для начала, откроем эту страницу в режиме просмотра кода. По идее, для динамического построения графиков может использоваться xml или json. Поиск в коде находит нам следующую строку:

<a class="link link_ajax link_theme_normal i-bem" data-bem='{"link":{}}' tabindex="0" href="/quotes/index.html">Ещё</a></div></div><div class="quote i-bem" data-bem='{"quote":{"signValDigit":4,"animation":true,"url":"/quotes/graph_1.json"}}'>

Интересует именно ссылка “/quotes/graph_1.json”. Вспоминаем HTML, понимаем, что это ссылка на данные от корня сайта, иными словами, она имеет вид https://news.yandex.ru/quotes/graph_1.json.

Теперь надо разобраться, как импортировать json в R. Ищем. Первая же ссылка дает ответ.

 

Необходимо установить пакет и выполнить команды:

install.packages("rjson") 
library("rjson") 
json_file <- "https://news.yandex.ru/quotes/graph_1.json" 
json_data <- fromJSON(file=json_file)

Попробуем код, с учетом того, что получаем списковые данные (list), а нам нужна таблица (data frame), конвентируем хитрым образом список.

# install.packages("rjson")
library("rjson")
json_file <- "https://news.yandex.ru//quotes/graph_1006.json" 
l <- fromJSON(file=json_file) 
df <- data.frame(matrix(unlist(l$prices), nrow= length(l$prices), byrow=T),stringsAsFactors=FALSE) 
tail(df) 
##                X1    X2
## 6302 1.481748e+12 53.79
## 6303 1.481835e+12 54.19
## 6304 1.481921e+12 55.26
## 6305 1.481927e+12 55.33
## 6306 1.482180e+12 54.76
## 6307 1.482235e+12 55.46
df$Dat=format(as.Date(df$X1/3600/24/1000, origin = "1970-01-01"),"%Y-%m-%d") 
tail(df)
##                X1    X2        Dat
## 6302 1.481748e+12 53.79 2016-12-14
## 6303 1.481835e+12 54.19 2016-12-15
## 6304 1.481921e+12 55.26 2016-12-16
## 6305 1.481927e+12 55.33 2016-12-16
## 6306 1.482180e+12 54.76 2016-12-19
## 6307 1.482235e+12 55.46 2016-12-20

Вроде все работает. Напишем функцию, которая будет получать данные с Yandex и возвращать в виде таблицы. В качестве первого аргумента передаем цифровой код Яндекс (смотрим в адресной строке), в качестве второго задаем имя колонки:

GetYandexData<-function(idx,valuename="Value") {
  json_file <- paste0("https://news.yandex.ru//quotes/graph_",idx,".json")
  l <- fromJSON(file=json_file)
  df <- data.frame(matrix(unlist(l$prices), nrow= length(l$prices), byrow=T),stringsAsFactors=FALSE)
  df$Dat=format(as.Date(df$X1/3600/24/1000, origin = "1970-01-01"),"%Y-%m-%d")
  names(df)[2]<-valuename
  return(df[,c(3,2)]) 
}

z1<-GetYandexData(1006,"Brent")
z2<-GetYandexData(10,"Gold")
z3<-GetYandexData(1,"USD")

mytable<-merge(merge(z1,z2),z3)
tail(mytable)
##             Dat Brent   Gold     USD
## 5107 2016-12-16 55.26 1135.4 61.7515
## 5108 2016-12-16 55.26 1136.8 61.7515
## 5109 2016-12-16 55.33 1135.4 61.7515
## 5110 2016-12-16 55.33 1136.8 61.7515
## 5111 2016-12-19 54.76 1141.0 61.7931
## 5112 2016-12-20 55.46 1134.4 61.7967

Новогодние ёлочки на графике

Можно было бы на этом остановиться, но посмотрим как  можно построить интересный график с помощью расширения ggplot2.

Добавим технические колонки в отдельной таблице

graphData <- mytable
graphData$year=as.factor(format(as.Date(graphData$Dat),"%Y"))
graphData$month=as.factor(format(as.Date(graphData$Dat),"%m"))
graphData$wd=as.factor(format(as.Date(graphData$Dat),"%u"))
tail(graphData)
##             Dat Brent   Gold     USD year month wd
## 5107 2016-12-16 55.26 1135.4 61.7515 2016    12  5
## 5108 2016-12-16 55.26 1136.8 61.7515 2016    12  5
## 5109 2016-12-16 55.33 1135.4 61.7515 2016    12  5
## 5110 2016-12-16 55.33 1136.8 61.7515 2016    12  5
## 5111 2016-12-19 54.76 1141.0 61.7931 2016    12  1
## 5112 2016-12-20 55.46 1134.4 61.7967 2016    12  2
# "В лесу родилась ёлочка..."
# См. http://www.r-bloggers.com/geom_christmas_tree-a-new-geom-for-ggplot2-v2-0/
# Нижеследующий код нужен для построения елочек
library(ggplot2)
GeomChristmasTree <- ggproto("GeomChristmasTree", Geom,
 required_aes = c("x", "y"),
 default_aes = aes(shape = 19, colour = "black", 
 fill = "green4", size = 3,
 linetype = 1, alpha = 1,
 fontsize = 1),
 draw_key = draw_key_polygon,
 
 draw_panel = function(data, panel_scales, coord) {
 coords <- coord$transform(data, panel_scales)
 
 # each tree has 4*branches + 3 points
 if (length(coords$size) == 1) {
 tsize <- rep(pmax(1, round(coords$size)), length(coords$x))
 theight <- rep(pmax(0, round(coords$size)), length(coords$x))
 } else {
 tsize <- pmax(1, round(coords$size))
 theight <- pmax(0, coords$size)
 }
 
 # scale factors
 r01x <- diff(range(coords$x))/100
 r01y <- diff(range(coords$y))/100
 
 # coords
 longx <- unlist(lapply(seq_along(coords$x), function(i) {
 if (tsize[i] == 1) {
 dx <- -c(0.3, 0.3, 1.2, 0, -1.2, -0.3, -0.3)
 } else {
 dx <- -c(0.3, 0.3, rep(c(1.2,0.3), tsize[i]-1), 1.2, 0, -1.2, rep(c(-0.3,-1.2), tsize[i]-1), -0.3, -0.3)
 }
 r01x*dx + coords$x[i]
 }))
 longy <- unlist(lapply(seq_along(coords$y), function(i) {
 if (tsize[i] == 1) {
 dy <- c(-0.5, 0, 0, theight[i], 0, 0, -0.5)
 } else {
 dy <- c(-0.5, 0, 0, rep(1:(tsize[i]-1), each=2), theight[i], rep((tsize[i]-1):1, each=2), 0, 0, -0.5)
 }
 r01y*dy + coords$y[i]
 }))
 longid <- unlist(sapply(seq_along(coords$y), function(i) {
 rep(i, each=4*tsize[i]+3)
 }))
 
 grid::polygonGrob(
 longx, 
 longy,
 id = longid,
 gp = grid::gpar(col = coords[,"colour"],
 fill = coords[,"fill"],
 fontsize = 10)
 )
 }
)
geom_christmas_tree <- function(mapping = NULL, data = NULL, stat = "identity",
                                position = "identity", na.rm = FALSE, show.legend = NA, 
                                inherit.aes = TRUE, ...) {
  layer(
    geom = GeomChristmasTree, mapping = mapping,  data = data, stat = stat, 
    position = position, show.legend = show.legend, inherit.aes = inherit.aes,
    params = list(na.rm = na.rm, ...)
  )
}
# "В лесу она росла..."

# Строим график зависимости курса от цены на нефть


ggplot(subset(graphData,year=="2016"), aes(x=Brent, y=USD)) + 
  stat_density_2d(aes(color=month))+
    geom_christmas_tree(aes(fill=month,size=wd)) +
  labs(x="Цена на Нефть Brent (ICE.Brent), USD/баррель",y="Курс USD ЦБ РФ, руб.")+
  scale_fill_discrete(name = "Месяц")+
  scale_size_discrete(guide=FALSE)+
  scale_color_discrete(guide=FALSE)+
  theme_bw()+theme(text=element_text(size=14))
## Warning: Using size for a discrete variable is not advised.

# Сохраняем картинку. Размер в дюймах.
ggsave("Pic1.png",width=6,height=6,dpi=300)