Archiv der Kategorie: Tools

Using Stylo in Python

Why would you do that?

Since a couple of years I have been using stylometric methods to analyse texts. I learned to use the great stylometric tool Stylo (written in R) at the European Summer School of Digital Humanities in Leipzig from two of the developers: Maciej Eder and Jan Rybicki.

Some months after I started my PhD as a member of the junior research group “Computational Literary Genre Stylistics” CLiGS, guided by Christof Schöch, at theat the Computerphilologie Professorship (hold by Prof. Jannidis) at the University of Würzburg, Germany. I was told that I had to learn Python because that was the programming mother tongue of the department. And I did so. Since then, many of my projects are a mix of very basic R script that call Stylo, and other more sofisticated scripts in Python that make the preprocess and the evaluation.

I am not the only person in this R-Python situation; actually in the last years at least two tools for Stylometry have been written in Python: Pystyl and PyDelta. So, why do I keep working with Stylo if I know more Python? For several reasons:

  • Stylo is very well documented (installation, preparation of the corpus, general use…)
  • It has a mailing group where you get answers and help
  • It has been tested by hundreds of researchers
  • The developers teach about the tool
  • And they use the feedback of these workshops to improve Stylo (I have seen Maciej speed-coding some changes in Stylo during the class, uploading to CRAN, and asking the people to update Stylo)
  • Because my PhD-tutors recommend me to do so

My stylometric tests are becoming more and more complex so it is starting to be a pain to jump all the time between two groups of scripts. I knew that one can use other programming languages inside Python, so I thought it was worth a try to see if it was possible to use R and Stylo in Python.

This blog post and its sibling Notebook (that you can download as a Git Repository with the corpus and the output data) are the first findings. I would be really happy to receive opinion and feedback.


The module that we are going to use is rpy2, which allows you to work with R in Python. Since it is very possible that this module it is not in your computer, you have install it, for example using pip3 (more info in its documentation:

  • sudo pip3 install rpy2

That was not difficult, but to make it work was. After some time I realised that the problem was the version of R in my computer. Although the documentation of rpy2 says that a 3.0 version of R should be ok, it was not. Updating R in Ubuntu was trickier than expected, so I uninstalled and reinstalled R and Stylo again, making sure that R’s version was higher than 3.0. I am currently working with 3.3.

So, enough talking, if you have already installed rpy2, let’s import it:

I am not going to explain how exactly rpy2 works (because it is not the poing of this notebook and because I couldn’t). Let’s just say that whenever we see anything starting with R., it will be a R object that we can call from Python. Example:

We can convert these objects to Python objects:

Stylo in Python

In the same way we can call Stylo in Python:

Maybe it gives us a warning messages RRuntimeWarning: I think the problem is in the kind of answer that Stylo gives you in command line of R while running, that cannot give you in the same ways in Python. Does anyone know how to fix that?

In the repository of this Notebook you can find a subfolder with one Spanish corpus of the CLiGS Textbox (, prepared for stylometric tests. So I will define the path just as the current folder and I will call Stylo without the graphical user interface (if I would need the GUI we would just work in R!).

It is cool to see the answers of Stylo in a Jupyter Notebook running on Python, right?

When it is finished, a pop-up window from R will appear with the classic dendrogram that we all know:

Passing arguments

Now, how can I define the arguments for Stylo? Because, as explained in the documentation of Stylo, the arguments for maximum and minimum MFW are called mfw.min and mfw.max. Let’s try that:

Python complains: it doesn’t expect a dot in a variable name. The grammar of R and Python are not compatible. For this cases the documentation of rpy2 ( recommends to pass the arguments as a python dictionary in which the keys are strings with the names of the arguments in Stylo. Example with a couple of arguments:

Or we can define pass arguments for the kind of analysis, output that we want, the size of the n-gram…:

Now we have in our folder all the files that we have asked: png, distance table, features used… Nice!

But what if I want to work further with this data in Python?

Using the data from Stylo in Python

In the cell above I have called stylo() and saved its output in a variable called I_love_this_stuff (following the documentation of stylo 😉 ):

As we see, this variable is a ListVector of length 9. Each of these items contain different information from the analysis I have done. Let’s print the 100 first characters of the first items:

The first item contains actually the distance matrix:

As we see, this object is a matrix in R. Working in Python we would be happier with a Pandas Dataframe. For doing that, we convert first the matrix to a Numpy array, we use this array to load I_love_this_stuff to the dataframe, and we pass the names of the rows and the columns.

There you have your beautiful Delta Matrix of your corpus as Pandas Dataframe, using Stylo but working only with Python scripts. Yey!

Feedback, please!

This is just a try. Many things could be done in different ways, I have probably overseen things, maybe there are better ways to deal with this Python-R problem… So, please, let me know your thoughts (email, twitter, comments in the blog post…). Thanks in advance and thanks to Christof for his feedback about this Notebook!

How is the statistical typical Spanish Modernist Novel?

I am currently preparing an article about stylometry and genre in which I correlate clusters with metadata. One of the present results is that those texts with non typical values in its metadata are better distinguished than the rest: non realistic, texts in which the action takes place in other times or other continents… It seems that the well known structuralist categories of marked and unmarked could help organize the texts and genres. In order to get boolean values (like “yes“ or “no“) I looked for the central tendencies of the texts: which is the typical end of a novel of this period? Which is the typical gender or social level of its protagonist? How long are the novels of this period typically? Another way to see this information is: if I take a random novel from Spain and this period, what will I probably find?

For this purpose I am using the metadata of the Corpus de novelas de la Edad de Plata, from which you can find a first release on our GitHub account. The current state of the whole corpus contains around 250 novels from 1880 until 1939. I am not claiming that this corpus could be statistically representative for the literature of this period (although I am skeptical that the concept of representativeness, as used in statistics, could be any useful for humanist fields). Anyhow, this is a way for achieving very specific information about literature, or at least about this corpus.

For this purpose I have written a short script with the module Pandas of Python. You can find it in our Toolbox on GitHub (annotate > With the categorical values I have searched for the mode, and for the numerical values I have calculated the median (which is never worse than the mean, as far as I know).

So, the big question, what can I expect from a random novel of this period? Let’s start with things that we can be very confident about: it was written by a male author, the action takes place in the contemporary times, in Europe, and is realistic. 90% of the corpus agrees with that. But there are good odds about other aspects: it takes place in Spain, its protagonist is a young man with medium social level (neither starving, nor rich) with a sad ending, the text is written in third person, the history of literature doesn’t think that the text represents in any form the author’s life, and (congratulations!) is already in the public domain. All these aspects are true for more than 50% of the corpus.

From the numerical values we can know many other things: it was probably published in the the decade of the 1900, to be more specific in 1905. We have already said that its action takes place in contemporary times, but it reasonably lasts around a year. The text is about 65 000 words (around 250 pages) and presumably contains around 1500 paragraphs, from which around 40% contain dialogue. And it has only four verses, believably. We already know that the author was quite probably a man, but we could even perhaps guess that he lived 64 years, since he was born around 1866 and died around 1930. We even presume that he changed his ways of writing around 1890, so the random book comes from his second period. And finally we may also think that the author was quite important, because manuals of history of literature have actually dedicated a whole chapter to him.

And there are other aspects that are not present in the majority of the corpus, but that represent anyway the most common value. Not only the texts takes place in Spain: around a third of the action of the novels takes place in Madrid. We can also guess that the author wrote it in the late period of the modernism (with a big concept of the Generación del 98 being part of it) and this author probably also wrote collections of short stories. Actually there is 15% chance that the author was Pío Baroja since he was the most prolific author of this period (and it is also in the corpus). And, although it has only a 2% chances, the most common name of the protagonist of the text is Xavier de Bradomín.

Many of you will argue that it is impossible to read a novel written by Pío Baroja with a protagonist called Xavier de Bradomin: this name belongs to a fictional character of Valle-Inclán. And it is true, all this information doesn’t apply to the texts altogether; some parts contradict strongly others: how could possible lords have a medium social level? This script only seeks the central tendency of each category independently. There are many ways to get a sharper and more representative picture of the the literature of this period: better and more data (many of the information shows the bias of my corpus), not only using mode or median, having in consideration correlations between categories,etc.

But other aspects (realistic, contemporary, Europe, Spain, male author and protagonist…) are ideas very present in the history of the literature. With this playful post (I have really enjoyed discovering and writing about it!) I am only suggesting this way to scrutinise texts: this way of treating metadata provides statistical values that can summarize, tinge or reinforce different ideas about literature.

Verba Alpina: open data + elegant solutions

In the context of the Junge Forum Romanistik, there were workshops with a focus on digital tools in literary and linguistic studies organized by CLiGS together with the FJR and the AG Digitale Romanistik. In one of the workshops, Thomas Krefeld and Stephan Lücke presented the project Verba Alpina:

Screenshot from 2016-03-17 07:11:16This project studies dialectal data from the very multinational area of the Alps. The classical dialectal projects took a national approach that hides the linguistic processes that go across the border.  It impressed me for three reasons: two very simple and elegant solutions that they are applying in the project and how open the data and the tool are.
Verba Alpina: open data + elegant solutions weiterlesen