Elasticsearch and R

Last month I spent some time working with Elasticsearch and Kibana and I was trying to integrate it with other systems. For example connectiong Elasticsearch wiht Hive is very easy, but I wondered how about reading and saving data from R

Let’s use same NYC data describing vehicle collisions, available here.

Saving data to Elasticsearch

There is a package that makes interaction with ES very easy.

install.packages("elastic")
require(elastic)

connect(es_base = "localhost", es_port = "9200")

Let’s say that collisions is a data frame with our data that will be stored in Elastic. Saving data to the index is a one function call:

docs_bulk(collisions, index = "nyc_collisions")

If the index already exists you can try removing it first when clean upload is neccessary:

index_delete(index = "nyc_collisions")

Mappings

Unfortunately by default all text fields are analyzed, so in our case that can be not usfull for columns describing street:

Aggregating by analyzed text field

To prevent analyzing we need to specify mapping:

index_delete(index = "nyc_collisions")

index_create(index = "nyc_collisions")

mapping_create(index = "nyc_collisions", type = "nyc_collisions", body = '
{
  "nyc_collisions": {
    "properties": {
      "street": { "type": "string", "index": "not_analyzed" }
    }
  }
}')

docs_bulk(collisions, index = "nyc_collisions")

Now we can fully enjoy categorical variable:

Grouping by not analyzed text field

Readeing from Elasticsearch

There is a Search function (with capital “s”) which allows to perform searches on ES and fetch the results into R.

res <- Search(index = "nyc_collisions", 
                            q = "manhattan", 
                            size = 10, 
                            asdf = T)

where q is our query used to filter index, size specifies the number of rectors that will be retrived and asdf means to fetch the data as data frame.

Our final data frame is in res$hits$hits$’_source’:

resdf <- res$hits$hits$'_source'
resdf$date <- as.Date(resdf$date)
summary(resdf)

      date              borough               zip             lat             lon            street              killed 
 Min.   :2015-07-12   Length:10          Min.   :10006   Min.   :40.71   Min.   :-74.01   Length:10          Min.   :0  
 1st Qu.:2015-07-14   Class :character   1st Qu.:10025   1st Qu.:40.80   1st Qu.:-73.96   Class :character   1st Qu.:0  
 Median :2015-07-28   Mode  :character   Median :10026   Median :40.80   Median :-73.96   Mode  :character   Median :0  
 Mean   :2015-07-26                      Mean   :10024   Mean   :40.79   Mean   :-73.96                      Mean   :0  
 3rd Qu.:2015-08-05                      3rd Qu.:10027   3rd Qu.:40.81   3rd Qu.:-73.95                      3rd Qu.:0  
 Max.   :2015-08-07                      Max.   :10031   Max.   :40.83   Max.   :-73.95                      Max.   :0  
 pedestrians_injured
 Min.   :0          
 1st Qu.:0          
 Median :0          
 Mean   :0          
 3rd Qu.:0          
 Max.   :0    

Searching gets more complicated when we retrieve only specified fields, not the whole documents. We will have to unlist the list values manually, but it can be necessary to fit bigger datasets into memory.

Powstanie warszawskie

Pierwszego sierpnia obchodzona jest rocznica wybuchu powstania warszawskiego. Co roku jest to widoący temat we wszystkich mediach i niewątpliwie przekłada się to na zainteresowania internautów. Tego dnia czytelników szukających informacji o tym zrywie niepodległościowym jest zdecydowanie najwięcej.

Powstanie warszawskie - odsłony na polskiej Wikipedii

W tym roku odsłon na Wikipedii było o wiele mniej niż w poprzednich latach, ale być może jest to związane z większą znajomościa tematu w społeczeństwie. Poza tym zeszłoroczne obchody okrągłej 70 rocznicy siłą rzeczy mogły być bardziej akcentowane w mediach.

Poza 1 sierpnia artykuł o powstaniu warszawskim jest jeszcze często czytany na początku paździerknika, czyli w rocznicy zakończenia walk. Ta prawidlowość jest jednak dość słaba i pojawiła się dopiero w ostatnich latach.

Powstańcy

Które biografie były najczęściej czytane 1 sierpnia? Spośród 234 kobiet, które walczyły w 1944 roku i zostały opisane na Wikipedii zdecydowanie najwięcej odsłon miała strona Aliny Janowskiej. Poza tym sporo internautów czytało o Krystynie Krahelskiej (zginęła podczas powstania) i o Danucie Szaflarskiej.

Wśród mężczyzn biorących udział w walkach najczęciej czytano o Zbigniewie Ściborze-Rylskim (prawie 3000 odsłon). Sporo osób wspominało też Krzysztofa Kamila Baczyńskiego (ponad 2000 odsłon). Trzecia najczęściej czytana biografia może być pewnym zaskoczeniem — tą postacią był August Agbola O’Brown (715odsłon) i, jak czytamy na Wikipedii, był to jedyny czarnoskóry uczestnik powstania.

Miasto 44

W tym roku po staraniach m.in. Tomasza Lisa niemiecka telewizja publiczna ZDF wyemitowała 2 sierpnia wieczorem film Miasto 44. To wydarzenie było opisywane w pozostałych mediach (np. faz) i cieszyło się, wg opinii niektórych komentatorów, pewnym zainteresowaniem (natemat).

Powstanie warszawskie - odsłony na niemieckiej Wikipedii

Patrząc na odsłony niemieckojęzycznej Wikipedii można znaleźć informacje, iż rzeczywiście w tym roku najwięcej czytelników o powstaniu warszawskim było 2 sierpnia, czyli w dniu emisji filmu, a nie w rocznicę zrywu. Trudno jednak niezauważyć, że zainteresowanie tą tematyką u naszych zachodnich sąsiadów było dużo mniejsze niż np. przed rokiem. Dlatego choć emisja Miasta 44 była zauważona, to jedak nie było to wydarzenie poruszające tłumy telewidzów. Potwierdza to m.in ten raport z wirtualnemedia.pl, który pokazuje, że widzów przed telewizorami było ok. 1 mln, podczas gdy tydzień wcześniej o tej samej porze publiczność była 2,5 raza większa.

wikipediatrends

Chciałem na koniec jeszcze wspomnieć o fantastycznym pakiecie R, który bardzo ułatwia analizę liczby odsłon. Dzięki wikipediatrends możemy w kilku linijkach pobrać zagregowane dane do R bez konieczności obróbki logów z Wikipedii. Jest to spore ułatwienie i nie byłoby to możliwe bez serwisu http://stats.grok.se.

require(wikipediatrend)

pv <- wp_trend(
          page = c("Powstanie_warszawskie", "Warschauer_Aufstand"),
          from = '2010-01-01', to = '2015-08-04',
          lang = c("pl", "de")
      )

R: readHTMLTable

Last time I have found another useful function that could save your time when playing with R. Let’s say we have some tabular data on HTML page, like here. With readHTMLTable function from XML package reading it into R cannot be simpler:

> install.packages("XML") 
> require(XML)
>
> d <- readHTMLTable("http://en.wikipedia.org/wiki/Transistor_count")
> class(d)
[1] "list"

Each table was extracted and converted into data.frame. Let’s have a look on the first one:

> table_a <- d[[1]]
> head(table_a)
            Processor Transistor count Date of introduction   Manufacturer Process   Area
1          Intel 4004            2,300                 1971          Intel   10 µm 12 mm²
2          Intel 8008           3,500                 1972          Intel   10 µm 14 mm²
3 MOS Technology 6502         3,510[1]                 1975 MOS Technology    8 μm 21 mm²
4       Motorola 6800            4,100                 1974       Motorola    6 μm 16 mm²
5          Intel 8080            4,500                 1974          Intel    6 μm 20 mm²
6            RCA 1802            5,000                 1974            RCA    5 μm 27 mm²

The header cells from the table were used as column names.

Other read functions

It’s worth mentioning that other read function (like read.table or read.csv) can access documents hosted on a server — there is no need to download it first. I wish I learnt it sooner.

Connecting R to the Database

There are several ways to read data from RDBMS in R. One of the way is to do it via JDBC. This method is generic and it will be easy to switch to other database when needed. You don’t need to install any database specific clients — just copy a JDBC driver.

The following code in R connects to the database (Oracle in this example):

require(RJDBC)
driver <- JDBC("oracle.jdbc.driver.OracleDriver", "path/to/JDBC/Driver/ojdbc6.jar")
connection<-dbConnect(driver,"jdbc:oracle:thin:@ip_addres:1521:dbname","username","password")
d<-dbGetQuery(connection,"select * from user_tables")

I had problems when JAVA_HOME environment variable was pointing to JDK. In such case just change it to JRE directory. You can do it right from the R script with the following line:

Sys.setenv(JAVA_HOME="/path/to/java")

Remember that when setting this on Windows you will need to escape backslash: (i.e.: C:\\Program Files\\Java…)