Linguistic Interactive maps

It is possible to draw interactive linguistic maps using lingtypology

import lingtypology

1. Maps

1.1. Simplest example

The simplest script that draws a map with Romanian and Ukrainian languages will be:

m = lingtypology.LingMap(('Romanian', 'Afrikaans', 'Tlingit', 'Japanese'))
m.create_map()

If you have Glottocodes rather then language names, you can pass them as well (you need to set glottocode to True).

m = lingtypology.LingMap(('russ1263', 'afri1274', 'tlin1245', 'nucl1643'), glottocode=True)
m.create_map()

1.2. Save, Render or Save as Image

Be advised that create_map() returns a Folium map. In this notebook it is used because the map may be displayed this way.

To save your map as html run: m.save('map.html')

To get html as str run: m.render()

To get a png image run m.save_static(fname=fname) (if no arguments are given it will be returned as bytes).
geckodriver should be installed.
Note: save_static is an experimental method.

m.save_static()

1.3. Features

Simply drawing languages on a map is not very interesting. Let’s say that we want to mark some morphological features as different colors.

languages = ["Adyghe", "Kabardian", "Polish", "Russian", "Bulgarian"]
features = ["Agglutinative", "Agglutinative", "Inflected", "Inflected", "Analytic"]
m = lingtypology.LingMap(languages)
m.add_features(features)
m.create_map()

1.4. Customizing the map

As you can see, the map is not centered properly. It can be fixed with passing coordinates to the start_location attribute. You can change start zoom as well start_zoom. Also, you can change colors using the colors parameter. You can determine in which order features are placed in the legend using factor parameter.

m.start_location = (40, 40)
m.start_zoom = 3
m.add_features(
    features,
    colors=("#00FFFF", "#FF00FF", "#FFFF00"),
    factor=('Inflected', 'Analytic', 'Agglutinative')
)
m.create_map()

1.5. Popups

You can add popups using add_popups method. You can disable links to Glottolog by setting glottolog_links parameter to False.
Basically, you can set any html-code in the popups.
contents = ('Caucasus', 'Caucasus', 'Europe', 'Europe', 'Europe')
html = '''
<a href="https://en.wikipedia.org/wiki/{data}" target="_blank">
{data}
</a>
'''
m.add_popups([html.format(data=popup) for popup in contents], glottolog_links=False)
m.create_map()

1.6. Accessing Glottolog

You can also use lingtypology.glottolog to get some data from it. For example, I want to add language affiliations to popups.
See more details here.
affs = lingtypology.glottolog.get_affiliations(languages)
m.add_popups(affs)
m.create_map()

1.7. Customizing features and controls

You can pass additional parameters to the add_features method.
If for some reason you do not wish to use colors, you could use shapes.
If you want to add controls, you can do it as well.
m.add_features(features, use_shapes=True, control=True)
m.create_map()

1.8. Stroke features

It is possible to add another set of features to strokes of markers using add_stroke_features method.

stroke_features = ['Ergative', 'Ergative', 'Accusative', 'Accusative', 'Accusative']
m = lingtypology.LingMap(languages)
m.add_features(features)
m.add_stroke_features(stroke_features)
m.create_map()

1.9. Heatmaps

It would seem unfair if we could only draw circles.
Let’s draw a heatmap (the more density, the more languages with Large consonant inventory) using add_heatmap method.
It is from Wals. For more information consult this.
from lingtypology.datasets import Wals
wals_page = Wals('1a').get_df()

#First initialize LingMap without languages
m = lingtypology.LingMap()
#Add heatmap from  the Wals data
m.add_heatmap(wals_page[wals_page._1A_desc == 'Large'].coordinates)
m.create_map()
Citation for feature 1A:
Ian Maddieson. 2013. Consonant Inventories.
In: Dryer, Matthew S. & Haspelmath, Martin (eds.)
The World Atlas of Language Structures Online.
Leipzig: Max Planck Institute for Evolutionary Anthropology.
(Available online at http://wals.info/chapter/1, Accessed on 2019-08-09.)

1.10. Title

To add title, use title attribute.

m.title = 'Large Consonant Inventories'
m.create_map()

1.11. Lines

Let’s say we have this list of languages:

balkan = ['Modern Greek', 'Romanian', 'Bulgarian', 'Macedonian', 'Gheg Albanian']
other = ['Ukrainian', 'Turkish', 'Italian']
languages_all = balkan + other

We want the ones from Balkan sprachbund connected with lines with a popup that says ‘Balkan’. It is possible using add_line method.

#Let's get the coordinates that we need to draw a line
coordinates = map(lingtypology.glottolog.get_coordinates, balkan)
m = lingtypology.LingMap(languages_all)
m.add_line(coordinates, popup='Balkan')
m.start_location = (43, 27)
m.start_zoom = 5
m.create_map()

1.12. Customizing markers

It is possible to set opacity and width of markers.

m = lingtypology.LingMap(languages)
m.add_features(features, radius=7, opacity=0.9)
m.add_stroke_features(stroke_features, opacity=0.7)
m.create_map()

1.13. Start Location/Zoom shortcuts

There are some shortcuts that can allow not to choose start_location and start_zoom manually.

m = lingtypology.LingMap([
    'Irish', 'Estonian', 'Norwegian', 'Romanian', 'Polish',
    'Italian', 'Turkish', 'French', 'English', 'Spanish'
])
m.start_location = 'Central Europe'
m.create_map()

Full list of shortcuts:

m.start_location_mapping
{'Central Europe': {'start_location': (50, 0), 'start_zoom': 4},
 'Caucasus': {'start_location': (43, 42), 'start_zoom': 6},
 'Australia & Oceania': {'start_location': (-16, 159), 'start_zoom': 3},
 'Papua New Guinea': {'start_location': (-5, 141), 'start_zoom': 6},
 'Africa': {'start_location': (3, 22), 'start_zoom': 3},
 'Asia': {'start_location': (36, 100), 'start_zoom': 3},
 'North America': {'start_location': (51, -102), 'start_zoom': 3},
 'Central America': {'start_location': (19, -81), 'start_zoom': 4},
 'South America': {'start_location': (-27, -49), 'start_zoom': 3}}

1.14. Color gradients

There are two ways to use color gradients. Let’s say we have features called “Millions of native speakers”.

native_speakers = [0, 1, 5, 24, 44, 62, 78, 78, 378, 442]
m.legend_title = 'Native speakers (mln)'
m.legend_position = 'topright'

The first way is simply pass the features as numeric:

m.add_features(native_speakers, numeric=True)
m.colormap_colors = ('white', 'red')
m.create_map()

Or you can simply set attribute color to a gradient using gradient function.

m.add_features(native_speakers, colors=lingtypology.gradient(10, 'white', 'red'))
m.create_map()

1.15. Minicharts

You can add minicharts to the map using add_minicharts method. Just pass all the data.

Note, that if you are passing data as anything except for pandas.Series you should specify names parameter (e.g. names=('consonants', 'vowels')).

import pandas
data = pandas.read_csv(
    'https://raw.githubusercontent.com/ropensci/lingtypology/master/database_creation/ejective_and_n_consonants.csv',
    delimiter=',',
    header=0,
)
data = data[data.language != 'Paraguayan Guarani']
m = lingtypology.LingMap(data.language)
m.add_minicharts(data.consonants, data.vowels)
m.create_map()
It is possible to customize them using these parameters: 1. colors
Colors for your features. If not given, default colors (LingMap().colors) will be used.
  1. size Size of the chart. Please, bear in mind that they should be small. Default: 0.6.
  2. startangle Start angle. Default 90. Pie-chart only.
  3. labels Show values inside the chart. Pie-chart only.
  4. textprops Set text properties (matplotlib format). Default: None. E.g.: textprops={'color': 'red'}.
m = lingtypology.LingMap(data.language)
m.add_minicharts(
    data.consonants, data.vowels,
    colors = ('#0020c2', '#c22000'),
    size = 0.8,
    startangle = 45,
    labels = True,
    textprops = {'color': 'white'}
)
m.create_map()

You can also use bar charts.

m = lingtypology.LingMap(data.language)
m.add_minicharts(
    data.consonants, data.vowels,
    typ = 'bar',
    colors = ('blue', 'red'),
    size = 0.4
)
m.create_map()

1.16. Overlapping Features

Let’s say we want to see info about whether language: 1. is ergative; 2. has cases; 3. is slavic.

It is possible with add_overlapping_features method. It allows to draw several markers of different radius and color for each given language.

languages = ('Tsakhur', 'Russian', 'Bulgarian')
m = lingtypology.LingMap(languages)
m.add_overlapping_features([
    ['ergative', 'has cases'],
    ['has cases', 'slavic'],
    ['slavic']
])
m.create_map()

You can use these parameters: 1. radius Default radius. Default: 7. 2. radius_increment Radius increment. By how much the size of the marker increases with each additional feature. Default: 4. 3. mapping If you want to use custom colors, use this parameter. If it is not given, the default color will be used.

m.add_overlapping_features(
    [
        ['ergative', 'has cases'],
        ['has cases', 'slavic'],
        ['slavic']
    ],
    radius = 10,
    radius_increment = 5,
    mapping = {
        'ergative': '#e6194b',
        'has cases': '#4be619',
        'slavic': '#194be6'
    }
)
m.create_map()

1.17. Using Existing Folium Map

If you already have a folium.Map that you want to edit using lingtypology, you can pass it as base_map attribute.

import folium
folium_map = folium.Map((0, 0), zoom_start=2)
marker = folium.Marker((0, 0))
icon = folium.DivIcon(
    html='<img src="https://raw.githubusercontent.com/OneAdder' + \
    '/lingtypology/master/data_processing/waifu6060.jpg"></img>'
)
marker.add_child(icon)
folium_map.add_child(marker)

m = lingtypology.LingMap(('Russian', 'Afrikaans'))
m.base_map = folium_map
m.create_map()

1.18. Merging Maps

You can also draw two lingtypology maps the way it is described in 1.16. However, it is not recommended and may cause glitches.

You can use lingtypology.merge. Let’s merge examples from 1.12 and 1.13

m1 = lingtypology.LingMap([
    'Irish', 'Estonian', 'Norwegian', 'Romanian', 'Polish',
    'Italian', 'Turkish', 'French', 'English', 'Spanish'
])
m1.add_features(native_speakers, numeric=True)
m1.colormap_colors = ('white', 'red')
m1.legend_title = 'Native Speakers'
m1.legend_position = 'bottomleft'

m2 = lingtypology.LingMap(data.language)
m2.legend_title = 'Consonants/Vowels'
m2.add_minicharts(data.consonants, data.vowels)

m = lingtypology.merge(m1, m2)
m.create_map()

1.19. Using Different Tiles

You can change tiles using tiles attribute. Let’s use Stamen Terrain.

m2 = lingtypology.LingMap(data.language)
m2.tiles = 'Stamen Terrain'
m2.legend_title = 'Consonants/Vowels'
m2.add_minicharts(data.consonants, data.vowels, colors=('black', 'white'))
m2.create_map()

1.20. Using Elevation Data

lingtypology package contains data on elevation (raw data taken from here) for each language from Glottolog.
You can get elevation for any language using lingtypology.get_elevations function.
m = lingtypology.LingMap(data.language)
data['elevation'] = lingtypology.get_elevations(data.language)
m.add_features(data.elevation, numeric=True)
m.add_tooltips(data.elevation)
m.legend_position = 'bottomleft'
m.create_map()

2. Some real examples

2.1. Circassian Example

Let’s draw a map based on data from this CSV.

import pandas
circassian = pandas.read_csv(
    'https://raw.githubusercontent.com/ropensci/lingtypology/master/database_creation/circassian.csv',
    delimiter=',',
    header=0,
)
circassian.head()
latitude longitude village district dialect language
0 45.183330 39.666670 Khatukay ra Temirgoy Adyghe
1 43.092518 43.522085 Psygansu kbr Baksan Kabardian
2 43.217748 43.738020 Verkhny Lesken kbr Baksan Kabardian
3 43.260246 43.653788 Zhemtala kbr Baksan Kabardian
4 43.317842 43.876519 Erokko kbr Baksan Kabardian
coordinates = zip(list(circassian.latitude), list(circassian.longitude))
dialects = circassian.dialect
languages = circassian.language
popups = circassian.village
#Creating LingMap object
m = lingtypology.LingMap(languages)
#Setting up start location
m.start_location = (44.21, 42.32)
#Setting up start zoom
m.start_zoom = 7
#Inner features < dialect
m.add_features(dialects, opacity=0.7)
#Outer features < language
m.add_stroke_features(languages, opacity=0.8)
#Popups < village
m.add_popups(popups)
#Tooltips < language
m.add_tooltips(languages)
#Custom coordinates (override the ones from Glottolog)
m.add_custom_coordinates(coordinates)
#Inner legend title and position
m.legend_title = 'Dialects'
m.legend_position = 'bottomright'
#Outer legend title and position
m.stroke_legend_title = 'Languages'
m.stroke_legend_position = 'topright'
m.create_map()

2.2. Consonants Example

Map based on this data.

data = pandas.read_csv(
    'https://raw.githubusercontent.com/ropensci/lingtypology/master/database_creation/ejective_and_n_consonants.csv',
    delimiter=',',
    header=0,
)
m = lingtypology.LingMap(data.language)
m.legend_title = 'Consonants'
m.legend_position = 'bottomleft'
m.add_tooltips(data.consonants)
#If numeric is True, it will look like this
m.add_features(data.consonants, numeric=True)
m.create_map()

Go back up