Checking The Met open data consistency against Wikidata

This set of scripts will check the consistency of the Met data set and Wikidata.

For objects, we should check the title, accession number, creator, creation date and instance of info.

Import Met CSV database into a dataframe

This is more than 400,000 rows, so it may take 5-10 seconds or more

import csv
from urllib.request import urlopen
import codecs
# from tqdm import tqdm
# from tqdm._tqdm_notebook import tqdm_notebook
import requests
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from dateutil.parser import parse

# The Met's weekly CSV dump URL in Github is quite big at 250 Mbytes
# Comment out for now, since this is slow to load. 
# url = 'https://media.githubusercontent.com/media/metmuseum/openaccess/master/MetObjects.csv'

# Use local copy of CSV file for speed and read the CSV file into a pandas dataframe
url = 'metmuseum/MetObjects-20190425.csv'
met_df = pd.read_csv(url,low_memory=False)

Examine the structure of rows

Take a look at some of the rows. NaN means "not a number" or a blank from the CSV file.

met_df.sample(3)
Object Number Is Highlight Is Public Domain Object ID Department Object Name Title Culture Period Dynasty ... Locale Locus Excavation River Classification Rights and Reproduction Link Resource Metadata Date Repository Tags
36569 14.40.94 False True 42256 Asian Art Vase NaN China Qing dynasty (1644–1911), Kangxi period (1662–... NaN ... NaN NaN NaN NaN Ceramics NaN http://www.metmuseum.org/art/collection/search... 4/22/2019 8:00:03 AM Metropolitan Museum of Art, New York, NY Vases
470093 63.350.619.414.113 False False 764673 Drawings and Prints Print Tom Mix in "Hello Cheyenne" from Western Stars... NaN NaN NaN ... NaN NaN NaN NaN Prints|Ephemera NaN http://www.metmuseum.org/art/collection/search... 4/22/2019 8:00:03 AM Metropolitan Museum of Art, New York, NY Men|Portraits|Actors
304329 1970.635.3 False False 433907 Drawings and Prints Print Simeon, from The Twelve Sons of Jacob NaN NaN NaN ... NaN NaN NaN NaN Prints NaN http://www.metmuseum.org/art/collection/search... 4/22/2019 8:00:03 AM Metropolitan Museum of Art, New York, NY NaN

3 rows × 44 columns

Statistics on most used and unique terms

The most frequently used terms can be found in the row labeled "top." In summary:

  1. Drawings and prints departement has the most items
  2. Object number "62.635" is used four times, which we can investigate below.
met_df.describe(include=[np.object])
Object Number Department Object Name Title Culture Period Dynasty Reign Portfolio Artist Role ... Locale Locus Excavation River Classification Rights and Reproduction Link Resource Metadata Date Repository Tags
count 494311 494311 489851 463050 209050 89550 23284 11205 22217 285440 ... 15562 7329 15967 2098 437900 24940 494311 494311 494311 277566
unique 491608 19 28302 251441 7267 1811 381 380 3274 6326 ... 859 1352 364 230 1227 1427 494311 1 1 55172
top 62.635 Drawings and Prints Print Fragment American Edo period (1615–1868) Dynasty 18 reign of Amenhotep III Les Images De Tous Les Saincts et Saintes de L... Artist ... Cemetery debris MMA excavations Upper Sepik River Prints © Walker Evans Archive, The Metropolitan Museu... http://www.metmuseum.org/art/collection/search... 4/22/2019 8:00:03 AM Metropolitan Museum of Art, New York, NY Men|Portraits|Baseball|Athletes
freq 4 178182 101945 7011 28404 8879 7178 2730 601 115028 ... 1925 416 2387 361 76967 9204 1 494311 494311 9706

4 rows × 39 columns

met_df[met_df['Object Number'].str.match('^62.635$')]
Object Number Is Highlight Is Public Domain Object ID Department Object Name Title Culture Period Dynasty ... Locale Locus Excavation River Classification Rights and Reproduction Link Resource Metadata Date Repository Tags
267275 62.635 False True 396034 Drawings and Prints Print The Delivery of the Keys to Peter NaN NaN NaN ... NaN NaN NaN NaN Prints NaN http://www.metmuseum.org/art/collection/search... 4/22/2019 8:00:03 AM Metropolitan Museum of Art, New York, NY Sheep|Christ|Christian Imagery|Saint Peter|Keys
475029 62.635 False False 772842 Drawings and Prints Print Air NaN NaN NaN ... NaN NaN NaN NaN Prints NaN http://www.metmuseum.org/art/collection/search... 4/22/2019 8:00:03 AM Metropolitan Museum of Art, New York, NY NaN
475031 62.635 False False 772844 Drawings and Prints Print Water NaN NaN NaN ... NaN NaN NaN NaN Prints NaN http://www.metmuseum.org/art/collection/search... 4/22/2019 8:00:03 AM Metropolitan Museum of Art, New York, NY NaN
476670 62.635 False False 774810 Drawings and Prints Print Dilapidated Tower and Gothic Gate NaN NaN NaN ... NaN NaN NaN NaN Prints NaN http://www.metmuseum.org/art/collection/search... 4/22/2019 8:00:03 AM Metropolitan Museum of Art, New York, NY NaN

4 rows × 44 columns

Examine random artist names

met_df['Artist Display Name'].sample(10)
25185                                                   NaN
284807                                            Gum, Inc.
297148          Josef Albers|Gemini G.E.L.|Kenneth E. Tyler
72817                                                   NaN
79348                                          Emilio Pucci
241931    Pablo Picasso|Aldo and Piero Crommelynck|Galer...
199833                                                  NaN
316851                                                  NaN
397383         American Tobacco Company|W. Duke, Sons & Co.
492946                     Anonymous, British, 18th century
Name: Artist Display Name, dtype: object

Public domain works

met_df['Is Public Domain'].value_counts().plot.pie(autopct='%.0f')
<matplotlib.axes._subplots.AxesSubplot at 0x7f64b27c0d30>

Most frequent artists

Photographer Walker Evans leads the list here, followed by publishers of trade or baseball cards (Kinney Brothers Tobacco, Allen & Ginter, W. Duke, Sons, et al), ephemera and other materials.

met_df['Artist Display Name'].value_counts()[:50]
Walker Evans                                                  9353
Kinney Brothers Tobacco Company                               4282
Unknown                                                       3586
Allen & Ginter                                                3184
W. Duke, Sons & Co.                                           3148
Topps Chewing Gum Company                                     3068
Goodwin & Company                                             2746
Brewster & Co.                                                2696
Bowman Gum Company                                            2633
American Tobacco Company                                      2122
Exhibit Supply Company                                        1664
The Diamond Match Company                                     1305
Goudey Gum Company                                            1208
Anonymous                                                     1094
Reginald Marsh                                                1007
Anonymous, British, 19th century                               989
W. Duke, Sons & Co.|Knapp & Company                            984
Giovanni Battista Piranesi                                     930
Auguste Edouart                                                870
Jacques Callot|Israël Henriet                                  862
William S. Kimball & Company                                   829
Gum, Inc.                                                      798
Turkish Trophies Cigarettes                                    751
National Chicle Gum Company, Cambridge, Massachusetts          740
Albrecht Dürer                                                 729
John Singer Sargent                                            716
Wenceslaus Hollar                                              715
Jacques Androuet Du Cerceau                                    686
Utagawa Hiroshige                                              673
Anonymous, French, 19th century                                621
J. Claude Frères & Co.|Unknown Designer                        602
Jean Le Pautre|Pierre Mariette le fils                         589
W. Duke, Sons & Co.|American Tobacco Company                   587
American Tobacco Company|W. Duke, Sons & Co.                   564
American Caramel Company, Lancaster and York, Pennsylvania     559
Giorgio di Sant'Angelo                                         555
Stefano della Bella                                            549
James McNeill Whistler                                         535
Unidentified Artist                                            523
Jules-Edmond-Charles Lachaise|Eugène-Pierre Gourdet            519
Jacques Callot                                                 516
Anonymous, French, 18th century                                501
Meissen Manufactory                                            494
André-Adolphe-Eugène Disdéri                                   490
Stephen Shore                                                  469
Charles James                                                  465
Thomas Rowlandson                                              464
Alphonse Bertillon                                             440
Katsushika Hokusai                                             422
American Caramel Company, Philadelphia                         417
Name: Artist Display Name, dtype: int64

Anonymous creators

Many entries in the Met database are "Unknown", "Anonymous" or "Anonymous..." with the addition of some qualifying details. Sometimes it is "Anonymous|..." with a pipe symbol, and other details are included. Here are the most frequent uses of "Anonymous." We should somehow capture this info in Wikidata, but it's possible that we might not want to and just infer the era instead from the artwork's Wikidata inception time?

Question - Should we make keep this distinction on "Unknown" and "Anonymous"?

Question - Should we capture the nationality and era of the "Anonymous" creator in Wikidata?

met_df[met_df['Artist Display Name'].str.match('Anonymous',na=False)]['Artist Display Name'].value_counts()[:50]
Anonymous                                                                                                      1094
Anonymous, British, 19th century                                                                                989
Anonymous, French, 19th century                                                                                 621
Anonymous, French, 18th century                                                                                 501
Anonymous, Italian, 16th century                                                                                254
Anonymous, American, 19th century                                                                               233
Anonymous, Italian, Roman-Bolognese, 17th century                                                               230
Anonymous, French, 16th century                                                                                 207
Anonymous, British, 18th century                                                                                192
Anonymous, Alsatian, 19th century                                                                               180
Anonymous, Italian, 17th century                                                                                172
Anonymous, American, 20th century                                                                               169
Anonymous, French, 20th century                                                                                 166
Anonymous, Italian, Piedmontese, 18th century                                                                   158
Anonymous, Italian, 19th century                                                                                123
Anonymous, Italian, first half of the 18th century                                                              100
Anonymous, Italian, 18th century                                                                                 97
Anonymous, Czech, early 20th century                                                                             90
Anonymous, German, 19th century                                                                                  86
Anonymous, German, 15th century                                                                                  83
Anonymous, Dutch, 17th century                                                                                   83
Anonymous, French, 17th century                                                                                  62
Anonymous, Irish, 19th century                                                                                   55
Anonymous, Italian or Spanish, late 15th to early 16th century|Master F|Giovanni Battista di Jacopo Cennini      50
Anonymous, American, 20th century|American Lithographic Co.                                                      46
Anonymous, Spanish, School of Seville, 17th century                                                              45
Anonymous, American, 19th to 20th centuries                                                                      37
Anonymous, 19th century                                                                                          35
Anonymous, German, 18th century                                                                                  32
Anonymous|Remondini Family                                                                                       32
Anonymous, German, 16th century                                                                                  32
Anonymous, Italian                                                                                               31
Anonymous, French, 18th century|Antoine Caire-Morand|Anonymous, French, 19th century                             28
Anonymous, Netherlandish, 16th century                                                                           28
Anonymous, Italian, 17th or 18th century                                                                         27
Anonymous, French, 16th century|Jacques Androuet Du Cerceau                                                      27
Anonymous, 17th century|Guido Reni                                                                               26
Anonymous, Chinese, 19th century                                                                                 26
Anonymous|Jacques Callot                                                                                         25
Anonymous, Italian, 16th century|Parmigianino (Girolamo Francesco Maria Mazzola)                                 25
Anonymous, Spanish, School of Seville, 17th century|Pedro  Duque Cornejo                                         25
Anonymous, American, 18th century                                                                                25
Anonymous|Antonio Lafreri                                                                                        24
Anonymous, British, early 19th century                                                                           24
Anonymous, French                                                                                                23
Anonymous, Japanese, 19th Century                                                                                23
Anonymous, British, late 18th–early 19th century                                                                 23
Anonymous, Italian, 16th century|Enea Vico                                                                       22
Anonymous, German, 17th century                                                                                  21
Anonymous, British                                                                                               20
Name: Artist Display Name, dtype: int64
ax = met_df[met_df['Artist Display Name'].str.match('Anonymous',na=False)]['Artist Display Name'].value_counts()[:25].plot(kind='barh')

ax.spines['right'].set_visible(False)
ax.spines['top'].set_visible(False)
ax.spines['left'].set_visible(False)
ax.spines['bottom'].set_visible(False)

# Switch off ticks
ax.tick_params(axis="both", which="both", bottom=False, top=False, labelbottom=True, left=False, right=False, labelleft=True)

# Draw vertical axis lines
vals = ax.get_xticks()
for tick in vals:
    ax.axvline(x=tick, linestyle='dashed', alpha=0.4, color='#eeeeee', zorder=1)

# Set x-axis label
ax.set_xlabel("Count", labelpad=20, weight='bold', size=12)

# Set y-axis label
ax.set_ylabel("Artist", labelpad=20, weight='bold', size=12)

# Format y-axis label
# ax.xaxis.set_major_formatter(StrMethodFormatter('{x:,g}'))
    
ax.invert_yaxis()
met_df['Artist Display Name'].isin(['Anonymous']).value_counts(normalize=True)
False    0.997787
True     0.002213
Name: Artist Display Name, dtype: float64

Let's take a look at some of the examples of using a pipe (|) in the Anonymous entries

Question - Is there a consistent interpretation of the pipe symbol, in terms of it being an "and" or an "or" ... or does it depend on the department and their use of it differently?

met_df[met_df['Artist Display Name'].str.match('^Anonymous.*\|',na=False)]['Artist Display Name']
30538     Anonymous, Italian|Enea Vico|Polidoro da Carav...
140504    Anonymous Flemish weavers|Pieter Coecke van Aelst
207275    Anonymous, Netherlandish, 19th century|G. van ...
207621    Anonymous, German, 19th century|Anonymous, Ger...
207622    Anonymous, German, 19th century|Anonymous, Ger...
207629    Anonymous, German, 16th century|Anonymous, Swi...
207759                       Anonymous|Marcantonio Raimondi
207795    Anonymous, Swiss, 16th Century|Niklaus Manuel ...
207890    Anonymous, American, 19th century|Century Maga...
208017    Anonymous, Dutch, 17th century|Allart van Ever...
208018    Anonymous, Netherlandish, 17th century|Anonymo...
208020    Anonymous, Netherlandish, 17th century|Willem ...
208023    Anonymous, Dutch, 17th century|Anonymous, Dutc...
208024    Anonymous, Netherlandish, 17th century|Anonymo...
208025    Anonymous, Netherlandish, 17th century|Anonymo...
208027    Anonymous, Dutch, 17th century|Anonymous, Dutc...
208028    Anonymous, Flemish, 18th century|Jan Brueghel ...
208029    Anonymous, Flemish, 18th century|Jan Brueghel ...
208083    Anonymous, Netherlandish, 16th century|Anonymo...
208253    Anonymous, Netherlandish, 16th century|Jan de ...
208256    Anonymous, Netherlandish, 16th century|Anonymo...
208262    Anonymous, Flemish, 17th century|Anthony van Dyck
208268    Anonymous, Flemish, 18th century|Anonymous, Ne...
208467    Anonymous, German, 19th century|Moritz von Sch...
208495    Anonymous, German, 16th century|Hans Holbein t...
208522    Anonymous, German, 19th century|Anonymous, Ger...
208528    Anonymous, German, 19th century|Anonymous, Ger...
208544    Anonymous, German, 19th century|Anonymous, Ger...
208563    Anonymous, German, 16th century|Friedrich Sustris
208609    Anonymous, Netherlandish, 16th century|Anonymo...
                                ...                        
493117                           Anonymous|Remondini Family
493122                           Anonymous|Remondini Family
493124                           Anonymous|Remondini Family
493125                           Anonymous|Remondini Family
493135                           Anonymous|Remondini Family
493138                           Anonymous|Remondini Family
493140                           Anonymous|Remondini Family
493142                           Anonymous|Remondini Family
493143                           Anonymous|Remondini Family
493149                           Anonymous|Remondini Family
493175                           Anonymous|Remondini Family
493203                           Anonymous|Remondini Family
493214                           Anonymous|Remondini Family
493215                           Anonymous|Remondini Family
493222                           Anonymous|Remondini Family
493229                           Anonymous|Remondini Family
493230                           Anonymous|Remondini Family
493231                           Anonymous|Remondini Family
493233                           Anonymous|Remondini Family
493254                           Anonymous|Remondini Family
493257                           Anonymous|Remondini Family
493260                           Anonymous|Remondini Family
493261                           Anonymous|Remondini Family
493262                           Anonymous|Remondini Family
493291    Anonymous, British, early 19th century|Rudolph...
493293     Anonymous, British, 19th century|George Thompson
493294     Anonymous, British, 19th century|George Thompson
493517    Anonymous, British, 19th century|Henry William...
493525    Anonymous, British, 19th century|Henry William...
494020                           Anonymous|Remondini Family
Name: Artist Display Name, Length: 1277, dtype: object
met_df[met_df['Artist Display Name'].str.match('Anonymous',na=False)]['Artist Display Name'].sample(10)
218987             Anonymous, Italian, 17th or 18th century
254418    Anonymous, French, 16th century|Anonymous, 16t...
234504                      Anonymous, French, 18th century
263700                      Anonymous, French, 19th century
282318    Anonymous, Italian or Spanish, late 15th to ea...
232814                      Anonymous, French, 16th century
262929    Anonymous, Italian, 16th century|Parmigianino ...
258120                     Anonymous, British, 19th century
242829    Anonymous, Italian, 16th century|Enea Vico|Ant...
213259    Anonymous, Italian, Roman-Bolognese, 17th century
Name: Artist Display Name, dtype: object

Send Wikidata Query to pick up Met objects

Met objects are currently (April 2019) modeled slightly differently, so one goal of the project is to normalize this and make it consistent. There are currently two different methods to pick up Met objects:

  1. Anything with Met ID (P3634)
  2. Anything with inventory number (P217) qualified with collection (P195) set to Met (Q160236)

For a SPARQL query, these two are combined with UNION, and optional fields returned.

wikidata_api_url = 'https://query.wikidata.org/bigdata/namespace/wdq/sparql'

query = '''
SELECT DISTINCT ?item ?inventorynumber ?metid ?creator ?creatorLabel ?inception 
WHERE 
{
  {
    ?item p:P217 [ ps:P217 ?inventorynumber ; pq:P195 wd:Q160236 ]  .
  } UNION {
    ?item wdt:P3634 ?metid .
  }
  OPTIONAL { ?item p:P217 [ ps:P217 ?inventorynumber ; pq:P195 wd:Q160236 ]  . }
  OPTIONAL { ?item wdt:P3634 ?metid . }
  OPTIONAL { ?item wdt:P170 ?creator . }
  OPTIONAL { ?item wdt:P571 ?inception . }

  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }
} 
'''

data = requests.post(wikidata_api_url, data={'query': query, 'format': 'json'}).json()

Examine some random records to understand the JSON structure

Now that we've made the SPARQL query, which may take 5-10 seconds, let's look at some of the raw JSON that is returned to understand how to parse it.

# Examine the return data by selecting a few random ones
import random
import pprint

pp = pprint.PrettyPrinter()
pp.pprint(random.choices(data['results']['bindings'], k=3))
[{'creator': {'type': 'uri',
              'value': 'http://www.wikidata.org/entity/Q21994042'},
  'creatorLabel': {'type': 'literal',
                   'value': 'Christian Peltenburg-Brechneff',
                   'xml:lang': 'en'},
  'inception': {'datatype': 'http://www.w3.org/2001/XMLSchema#dateTime',
                'type': 'literal',
                'value': '1990-01-01T00:00:00Z'},
  'inventorynumber': {'type': 'literal', 'value': '1991.107'},
  'item': {'type': 'uri', 'value': 'http://www.wikidata.org/entity/Q19922098'},
  'metid': {'type': 'literal', 'value': '633009'}},
 {'creator': {'type': 'uri', 'value': 'http://www.wikidata.org/entity/Q272045'},
  'creatorLabel': {'type': 'literal',
                   'value': 'Kitagawa Utamaro',
                   'xml:lang': 'en'},
  'inception': {'datatype': 'http://www.w3.org/2001/XMLSchema#dateTime',
                'type': 'literal',
                'value': '1795-01-01T00:00:00Z'},
  'inventorynumber': {'type': 'literal', 'value': 'JP1438'},
  'item': {'type': 'uri', 'value': 'http://www.wikidata.org/entity/Q59767790'}},
 {'inception': {'datatype': 'http://www.w3.org/2001/XMLSchema#dateTime',
                'type': 'literal',
                'value': '-0200-01-01T00:00:00Z'},
  'inventorynumber': {'type': 'literal', 'value': '1972.118.95'},
  'item': {'type': 'uri', 'value': 'http://www.wikidata.org/entity/Q29383948'},
  'metid': {'type': 'literal', 'value': '255408'}}]

Convert the WDQ JSON result to a dataframe

Make life easier by converting the JSON to a Pandas Dataframe, which is basically a 2D spreadsheet-like data structure. We're going to also do some integrity checks as we import. Most of the data are strings and numbers, but the "inception" is a formal date string in the format +1984-01-01T00:00:00Z and it's possible Wikidata has dates that validate but are illogical, like year 0. It will error out on these, and show up in pink below.

Problem - It is also possible inception is set to "Unknown value" in Wikidata which is tricky to handle in Python.

In SPARQL parlance, it would be tested like this:

?item wdt:P571 ?date .

FILTER isBLANK(?date) .

We're have to figure out how to best represent this while doing our data work, since a Python dateTime module is quite strict. Some research indicates that there is quite a need for this type of function of handling outliers, but there is no simple or pat solution.

(https://stackoverflow.com/questions/6697770/allowing-invalid-dates-in-python-datetime)

import logging as logger
import numpy as np

resultarray = []
for item in data['results']['bindings']:
    # Need to fill in 0 and not None for int64, or this will be cast as float64
    metid = item['metid']['value'] if 'metid' in item else 0
    inventorynumber = item['inventorynumber']['value'] if 'inventorynumber' in item else None
    cl = item['creatorLabel']['value'] if 'creatorLabel' in item else None
    
    # Dates are weird - they are usually like +1984-01-01T00:00:00Z
    #   They may also be "unknown" with or without a start and end time
    try:
        inception = parse(item['inception']['value']) if 'inception' in item else None
    except (TypeError, ValueError):
        logger.warning('failed to parse QID %s - time %r', item['item']['value'], item['inception']['value'])
    
    resultarray.append({
        'qid': int(item['item']['value'].replace('http://www.wikidata.org/entity/Q','')),
        'metid': int(metid),
        'creatorLabel': cl,
        'inception': inception,
        'inventorynumber': inventorynumber,
        }
    )

# resultarray

# Create a Pandas dataframe    
wd_metitems_df = pd.DataFrame(resultarray)

# wd_metitems_df.astype(dtype={'metid':np.int64})

wd_metitems_df.info()
WARNING:root:failed to parse QID http://www.wikidata.org/entity/Q63434597 - time 't1446348760'
WARNING:root:failed to parse QID http://www.wikidata.org/entity/Q29384398 - time '+0000-01-01T00:00:00Z'
WARNING:root:failed to parse QID http://www.wikidata.org/entity/Q62759189 - time 't1415987824'
WARNING:root:failed to parse QID http://www.wikidata.org/entity/Q62761150 - time 't1415987834'
WARNING:root:failed to parse QID http://www.wikidata.org/entity/Q29383804 - time '+0000-01-01T00:00:00Z'
WARNING:root:failed to parse QID http://www.wikidata.org/entity/Q29384504 - time '+0000-01-01T00:00:00Z'
WARNING:root:failed to parse QID http://www.wikidata.org/entity/Q59767196 - time 't1289340650'
WARNING:root:failed to parse QID http://www.wikidata.org/entity/Q59770772 - time 't1310128553'
WARNING:root:failed to parse QID http://www.wikidata.org/entity/Q29384348 - time '+0000-01-01T00:00:00Z'
WARNING:root:failed to parse QID http://www.wikidata.org/entity/Q29384385 - time '+0000-01-01T00:00:00Z'
WARNING:root:failed to parse QID http://www.wikidata.org/entity/Q29388327 - time '+0000-01-01T00:00:00Z'
WARNING:root:failed to parse QID http://www.wikidata.org/entity/Q29383961 - time '+0000-01-01T00:00:00Z'
WARNING:root:failed to parse QID http://www.wikidata.org/entity/Q29385894 - time '+0000-01-01T00:00:00Z'
WARNING:root:failed to parse QID http://www.wikidata.org/entity/Q61730536 - time 't1357619311'
WARNING:root:failed to parse QID http://www.wikidata.org/entity/Q61781606 - time '+0000-00-00T00:00:00Z'
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 10798 entries, 0 to 10797
Data columns (total 5 columns):
creatorLabel       9564 non-null object
inception          10417 non-null object
inventorynumber    10692 non-null object
metid              10798 non-null int64
qid                10798 non-null int64
dtypes: int64(2), object(3)
memory usage: 421.9+ KB

Examine some random records to check they are being imported correctly

wd_metitems_df.sample(15)
creatorLabel inception inventorynumber metid qid
6705 Robert Havell 1840-01-01 00:00:00+00:00 54.90.32 11042 20174458
4004 Emmanuel Tzanes 1663-01-01 00:00:00+00:00 33.79.18 437857 19913426
8214 anonymous 1350-01-01 00:00:00+00:00 25.120.289a-e 473891 20201854
2933 anonymous 1700-01-01 00:00:00+00:00 1976.100.13 436347 19913242
9540 None 0433-01-01 00:00:00+00:00 11.141 248499 29383763
1923 anonymous 1750-01-01 00:00:00+00:00 25.106.36 435939 19913745
1984 anonymous 1800-01-01 00:00:00+00:00 62.122.32 437665 19913880
10203 None 0265-01-01 00:00:00+00:00 55.11.5 254819 29383917
6913 Pavel Svinyin 1811-01-01 00:00:00+00:00 42.95.42 12729 20178059
6479 David Teniers the Younger 1655-01-01 00:00:00+00:00 1975.1.127 459069 20187112
5995 William Scott 1957-01-01 00:00:00+00:00 2007.49.87 492759 20190127
10725 None None None 38159 43712728
3366 Henry Colton Shumway 1843-01-01 00:00:00+00:00 2007.437 19718 19924795
8606 None 1800-01-01 00:00:00+00:00 1988.301 327369 29384521
5120 William P. Chappel 1870-01-01 00:00:00+00:00 54.90.514 10440 20175745

Wikidata items for The Met with 'anonymous' as creator

wd_metitems_df.creatorLabel.isin(['anonymous']).value_counts(normalize=True).plot.pie(autopct='%.0f')
<matplotlib.axes._subplots.AxesSubplot at 0x7f64a0e70128>
wd_metitems_df.creatorLabel.isna().value_counts(normalize=True).plot.pie(autopct='%.0f')
<matplotlib.axes._subplots.AxesSubplot at 0x7f64a840e400>
met_df['Artist Display Name'].notna().value_counts(normalize=True).plot.pie(autopct='%.0f')
<matplotlib.axes._subplots.AxesSubplot at 0x7f64a83cf240>
met_artist_notna_df = met_df[met_df['Artist Display Name']].notna().copy()
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-14-0d2376b2e4ca> in <module>
----> 1 met_artist_notna_df = met_df[met_df['Artist Display Name']].notna().copy()
      2 

/srv/paws/lib/python3.6/site-packages/pandas/core/frame.py in __getitem__(self, key)
   2915 
   2916         # Do we have a (boolean) 1d indexer?
-> 2917         if com.is_bool_indexer(key):
   2918             return self._getitem_bool_array(key)
   2919 

/srv/paws/lib/python3.6/site-packages/pandas/core/common.py in is_bool_indexer(key)
    122             if not lib.is_bool_array(key):
    123                 if isna(key).any():
--> 124                     raise ValueError(na_msg)
    125                 return False
    126             return True

ValueError: cannot index with vector containing NA / NaN values
met_df[met_df['Artist Display Name'].str.match('Anonymous')]
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-59-2bfae3594be6> in <module>
----> 1 met_df[met_df['Artist Display Name'].str.match('Anonymous')]

/srv/paws/lib/python3.6/site-packages/pandas/core/frame.py in __getitem__(self, key)
   2915 
   2916         # Do we have a (boolean) 1d indexer?
-> 2917         if com.is_bool_indexer(key):
   2918             return self._getitem_bool_array(key)
   2919 

/srv/paws/lib/python3.6/site-packages/pandas/core/common.py in is_bool_indexer(key)
    122             if not lib.is_bool_array(key):
    123                 if isna(key).any():
--> 124                     raise ValueError(na_msg)
    125                 return False
    126             return True

ValueError: cannot index with vector containing NA / NaN values

Wikidata items believed to be Met objects but missing Met Object ID statement

These items don't have Met Object ID (P3634) set but are in the list because the inventorynumber and collection->The Met Museum was set. We test to see if Met ID = 0.

wd_missing_metid_df = wd_metitems_df[wd_metitems_df['metid'] == 0].copy()

wd_missing_metid_df.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 96 entries, 126 to 10642
Data columns (total 5 columns):
creatorLabel       90 non-null object
inception          82 non-null object
inventorynumber    96 non-null object
metid              96 non-null int64
qid                96 non-null int64
dtypes: int64(2), object(3)
memory usage: 4.5+ KB

Take a peek at 10 random entries returned

wd_missing_metid_df.sample(10)
creatorLabel inception inventorynumber metid qid
10613 Katsushika Hokusai 1832-01-01 00:00:00+00:00 JP1430 0 61040874
9385 William Burges 1880-01-01 00:00:00+00:00 2006.427 0 63213640
10637 Seyed Mohammad Ehsaey 2012-01-01 00:00:00+00:00 2013.587 0 61781765
9985 Diosphos Painter None 61.11.14 0 47451050
9718 Kitagawa Utamaro 1795-01-01 00:00:00+00:00 JP1478 0 59770591
10638 anonymous 2012-01-01 00:00:00+00:00 59.611.10 0 61730536
9720 Kitagawa Utamaro 1800-01-01 00:00:00+00:00 JP1123 0 59767429
9704 Kitagawa Utamaro 1795-01-01 00:00:00+00:00 JP1277 0 59769601
10326 Adam Willaerts 1643-01-01 00:00:00+00:00 06.1303 0 30086759
10634 anonymous None 29.100.460 0 61627780

Use Pandas equivalent of a database join

Do an "inner" join that makes a new dataframe based on the Met database (met_df) but adds a new columns from the Wikidata query (wd_missing_metid_df) that supplies qid and Object Number/inventory number

merged_todo_metid_df = pd.merge(met_df, wd_missing_metid_df, how='inner', left_on='Object Number', right_on='inventorynumber')

Test some rows for sanity:

merged_todo_metid_df[['Object Number','Object ID','qid']].sample(5)
Object Number Object ID qid
68 17.12 336614 62588729
14 JP1438 45099 59767790
4 JP660 37107 61410267
69 59.611.10 343178 61730536
22 JP2915 49937 61040874

Generate Quickstatements to fix the problem

# To generate Quickstatements, iterate over the rows
# Desired output: Q43742238|P3634|26606
QS_ADDMISSING_METID='Q%s|P3634|%d'

for index, row in merged_todo_metid_df.iterrows(): 
    print (QS_ADDMISSING_METID % (row['qid'], row['Object ID']))
Q43742238|P3634|26606
Q63213640|P3634|35148
Q61627780|P3634|36040
Q59568838|P3634|37007
Q61410267|P3634|37107
Q62030437|P3634|37332
Q59767429|P3634|39647
Q59767196|P3634|40601
Q60701643|P3634|44900
Q61038375|P3634|44981
Q59308573|P3634|45028
Q59308573|P3634|45028
Q59308573|P3634|45028
Q59308573|P3634|45028
Q59767790|P3634|45099
Q60698954|P3634|45218
Q59764147|P3634|45477
Q59770772|P3634|45478
Q59766802|P3634|45479
Q61040892|P3634|49934
Q61040865|P3634|49935
Q61040922|P3634|49936
Q61040874|P3634|49937
Q61041026|P3634|49938
Q61040907|P3634|49939
Q61041068|P3634|49941
Q59631300|P3634|51137
Q47507931|P3634|51305
Q59630045|P3634|52001
Q59766990|P3634|52002
Q44368963|P3634|53422
Q59765080|P3634|53653
Q59569401|P3634|53656
Q61038881|P3634|54194
Q61038735|P3634|54195
Q62017563|P3634|54378
Q61038971|P3634|54438
Q59569591|P3634|54864
Q59576526|P3634|54865
Q59654234|P3634|54866
Q60591845|P3634|54871
Q59567425|P3634|55138
Q59768113|P3634|55193
Q59769601|P3634|55208
Q61040874|P3634|55466
Q59770351|P3634|55485
Q59770591|P3634|55565
Q59763396|P3634|55862
Q61410188|P3634|56183
Q59627942|P3634|57011
Q63352678|P3634|57542
Q62602848|P3634|78593
Q63352619|P3634|78608
Q62589117|P3634|78633
Q62589468|P3634|78633
Q62589587|P3634|78633
Q62589687|P3634|78633
Q62589709|P3634|78633
Q62018305|P3634|78637
Q62018117|P3634|78637
Q61992387|P3634|212209
Q61293075|P3634|252050
Q47451092|P3634|254349
Q47451050|P3634|255104
Q50943784|P3634|267426
Q41449677|P3634|336318
Q62588549|P3634|336603
Q62589932|P3634|336607
Q62588729|P3634|336614
Q61730536|P3634|343178
Q56239000|P3634|365099
Q56238864|P3634|365101
Q61930464|P3634|374000
Q61930529|P3634|374003
Q61593610|P3634|377674
Q56034162|P3634|444881
Q58874673|P3634|446861
Q58874673|P3634|446861
Q61781765|P3634|458738
Q60337457|P3634|459730
Q55835403|P3634|485540
Q20174026|P3634|725827

Wikidata items believed to be Met objects but missing inventory number statement

These items don't have inventory number set but are in the list because Met Object ID (P3634) was set. We test to see if Wikidata results for Met items has inventorynumber set to None.

FIX for this would be to generate and ingest Quickstatements to fill in inventory number.

Something like:

Q61876946|P217|"2003.161"|P195|Q160236

wd_missing_inventory_df = wd_metitems_df[wd_metitems_df['inventorynumber'].isnull()].copy()

wd_missing_inventory_df.sample(10)
creatorLabel inception inventorynumber metid qid
10739 None 1638-01-01 00:00:00+00:00 None 51873 61746498
10789 Pieter Brueghel the Elder 1558-01-01 00:00:00+00:00 None 338697 56604898
10757 Georges Braque 1909-01-01 00:00:00+00:00 None 500390 60517079
10695 Katsukawa Shunshō None None 39630 62794859
10697 Pablo Picasso 1914-01-01 00:00:00+00:00 None 490563 61884489
10731 None None None 646432 44178853
10748 None 1900-01-01 00:00:00+00:00 None 158194 30063394
10793 Giovanni Paolo Panini 1754-01-01 00:00:00+00:00 None 437245 3094651
10795 None 1550-01-01 00:00:00+00:00 None 812566 61781455
10777 None 1850-01-01 00:00:00+00:00 None 57871 61748802

Use Pandas equivalent of a database join

Do an "inner" join that makes a new dataframe based on the Met database (met_df) but adds a new columns from the Wikidata query (wd_missing_inventory_df) that supplies qid and matched metid

merged_todo_inventorynumber_df = pd.merge(met_df, wd_missing_inventory_df, how='inner', left_on='Object ID', right_on='metid')

merged_todo_inventorynumber_df[['Object Number','Object ID','qid']].info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 105 entries, 0 to 104
Data columns (total 3 columns):
Object Number    105 non-null object
Object ID        105 non-null int64
qid              105 non-null int64
dtypes: int64(2), object(1)
memory usage: 3.3+ KB
merged_todo_inventorynumber_df[['Object Number','Object ID','qid']].sample(5)
Object Number Object ID qid
89 CTO.128 500382 60596830
90 SL.17.2014.1.3 500390 60517079
80 66.25 468716 25936897
20 1989.363.123 51873 61746498
5 JP152 36631 60590430

Generate Quickstatements to fix the problem

# To generate Quickstatements, iterate over the rows
# Desired output: Q61876946|P217|"32767"|P195|Q160236

# It is possible that the inventory number does exist already, but is missing the qualifier
# For example, it may have:
#   Q61750964|P217|"66.109"
# but not:
#   Q61750964|P217|"66.109"|P195|Q160236

# We could just subtract

QS_ADDMISSING_INVENTORYNUMBER='Q%s|P217|"%s"|P195|Q160236'
QS_ADDMISSING_COLLECTION='Q%s|P195|Q160236|P217|"%s"'

for index, row in merged_todo_inventorynumber_df.iterrows(): 
    print (QS_ADDMISSING_INVENTORYNUMBER % (row['qid'], row['Object Number']))
    print (QS_ADDMISSING_COLLECTION % (row['qid'], row['Object Number']))
Q61750964|P217|"66.109"|P195|Q160236
Q61750964|P195|Q160236|P217|"66.109"
Q30993455|P217|"2016.797.21"|P195|Q160236
Q30993455|P195|Q160236|P217|"2016.797.21"
Q30994036|P217|"2016.797.17"|P195|Q160236
Q30994036|P195|Q160236|P217|"2016.797.17"
Q61750993|P217|"43.120.1208a, b"|P195|Q160236
Q61750993|P195|Q160236|P217|"43.120.1208a, b"
Q30063003|P217|"36.25.508"|P195|Q160236
Q30063003|P195|Q160236|P217|"36.25.508"
Q60590430|P217|"JP152"|P195|Q160236
Q60590430|P195|Q160236|P217|"JP152"
Q60579810|P217|"JP555"|P195|Q160236
Q60579810|P195|Q160236|P217|"JP555"
Q60628715|P217|"JP1122"|P195|Q160236
Q60628715|P195|Q160236|P217|"JP1122"
Q60601286|P217|"JP2739"|P195|Q160236
Q60601286|P195|Q160236|P217|"JP2739"
Q60567840|P217|"JP3118"|P195|Q160236
Q60567840|P195|Q160236|P217|"JP3118"
Q60568037|P217|"JP3129"|P195|Q160236
Q60568037|P195|Q160236|P217|"JP3129"
Q43712728|P217|"1982.220.7"|P195|Q160236
Q43712728|P195|Q160236|P217|"1982.220.7"
Q62794859|P217|"36.100.70"|P195|Q160236
Q62794859|P195|Q160236|P217|"36.100.70"
Q61751040|P217|"30.32.15"|P195|Q160236
Q61751040|P195|Q160236|P217|"30.32.15"
Q43742393|P217|"19.103.2"|P195|Q160236
Q43742393|P195|Q160236|P217|"19.103.2"
Q60628584|P217|"1996.463"|P195|Q160236
Q60628584|P195|Q160236|P217|"1996.463"
Q28126677|P217|"1991.134"|P195|Q160236
Q28126677|P195|Q160236|P217|"1991.134"
Q60590216|P217|"JP990"|P195|Q160236
Q60590216|P195|Q160236|P217|"JP990"
Q47544982|P217|"1985.227.1"|P195|Q160236
Q47544982|P195|Q160236|P217|"1985.227.1"
Q43376787|P217|"1999.263a, b"|P195|Q160236
Q43376787|P195|Q160236|P217|"1999.263a, b"
Q61746498|P217|"1989.363.123"|P195|Q160236
Q61746498|P195|Q160236|P217|"1989.363.123"
Q60920142|P217|"JP1016"|P195|Q160236
Q60920142|P195|Q160236|P217|"JP1016"
Q60572478|P217|"JP1121"|P195|Q160236
Q60572478|P195|Q160236|P217|"JP1121"
Q60595333|P217|"JP2394"|P195|Q160236
Q60595333|P195|Q160236|P217|"JP2394"
Q60706622|P217|"JIB5"|P195|Q160236
Q60706622|P195|Q160236|P217|"JIB5"
Q61409206|P217|"JIB69"|P195|Q160236
Q61409206|P195|Q160236|P217|"JIB69"
Q61413284|P217|"JIB80"|P195|Q160236
Q61413284|P195|Q160236|P217|"JIB80"
Q61748802|P217|"10.7.4"|P195|Q160236
Q61748802|P195|Q160236|P217|"10.7.4"
Q61876908|P217|"2002.325"|P195|Q160236
Q61876908|P195|Q160236|P217|"2002.325"
Q43648711|P217|"2015.300.301a–c"|P195|Q160236
Q43648711|P195|Q160236|P217|"2015.300.301a–c"
Q63243745|P217|"SL.17.2011.22.4"|P195|Q160236
Q63243745|P195|Q160236|P217|"SL.17.2011.22.4"
Q61781621|P217|"2011.127"|P195|Q160236
Q61781621|P195|Q160236|P217|"2011.127"
Q60682065|P217|"2013.736a–f"|P195|Q160236
Q60682065|P195|Q160236|P217|"2013.736a–f"
Q60704425|P217|"2013.738a, b"|P195|Q160236
Q60704425|P195|Q160236|P217|"2013.738a, b"
Q60570674|P217|"2013.852a, b"|P195|Q160236
Q60570674|P195|Q160236|P217|"2013.852a, b"
Q60571703|P217|"2013.853"|P195|Q160236
Q60571703|P195|Q160236|P217|"2013.853"
Q60571061|P217|"2013.858"|P195|Q160236
Q60571061|P195|Q160236|P217|"2013.858"
Q60571356|P217|"2013.859"|P195|Q160236
Q60571356|P195|Q160236|P217|"2013.859"
Q60704878|P217|"2013.875"|P195|Q160236
Q60704878|P195|Q160236|P217|"2013.875"
Q60704659|P217|"2013.878"|P195|Q160236
Q60704659|P195|Q160236|P217|"2013.878"
Q60701873|P217|"2013.881"|P195|Q160236
Q60701873|P195|Q160236|P217|"2013.881"
Q60571569|P217|"2013.897"|P195|Q160236
Q60571569|P195|Q160236|P217|"2013.897"
Q60705589|P217|"2013.726"|P195|Q160236
Q60705589|P195|Q160236|P217|"2013.726"
Q60661034|P217|"2013.729a–c"|P195|Q160236
Q60661034|P195|Q160236|P217|"2013.729a–c"
Q60661765|P217|"2013.730"|P195|Q160236
Q60661765|P195|Q160236|P217|"2013.730"
Q41601734|P217|"29.158.485"|P195|Q160236
Q41601734|P195|Q160236|P217|"29.158.485"
Q30063394|P217|"2009.300.3275a–c"|P195|Q160236
Q30063394|P195|Q160236|P217|"2009.300.3275a–c"
Q582428|P217|"24.232"|P195|Q160236
Q582428|P195|Q160236|P217|"24.232"
Q30263483|P217|"42.30.17a, b"|P195|Q160236
Q30263483|P195|Q160236|P217|"42.30.17a, b"
Q54965918|P217|"58.75.3"|P195|Q160236
Q54965918|P195|Q160236|P217|"58.75.3"
Q30262521|P217|"42.30.18a, b"|P195|Q160236
Q30262521|P195|Q160236|P217|"42.30.18a, b"
Q60646192|P217|"L.2011.66.56a, b"|P195|Q160236
Q60646192|P195|Q160236|P217|"L.2011.66.56a, b"
Q42186356|P217|"12.231.1"|P195|Q160236
Q42186356|P195|Q160236|P217|"12.231.1"
Q42149613|P217|"17.230.5"|P195|Q160236
Q42149613|P195|Q160236|P217|"17.230.5"
Q36446060|P217|"24.97.21a, b"|P195|Q160236
Q36446060|P195|Q160236|P217|"24.97.21a, b"
Q36446060|P217|"24.97.21a, b"|P195|Q160236
Q36446060|P195|Q160236|P217|"24.97.21a, b"
Q42244789|P217|"46.11.7"|P195|Q160236
Q42244789|P195|Q160236|P217|"46.11.7"
Q3209564|P217|"1976.646"|P195|Q160236
Q3209564|P195|Q160236|P217|"1976.646"
Q29881716|P217|"2005.100.20"|P195|Q160236
Q29881716|P195|Q160236|P217|"2005.100.20"
Q61876946|P217|"2003.161"|P195|Q160236
Q61876946|P195|Q160236|P217|"2003.161"
Q61781606|P217|"1987.394.544"|P195|Q160236
Q61781606|P195|Q160236|P217|"1987.394.544"
Q26221327|P217|"62.151"|P195|Q160236
Q26221327|P195|Q160236|P217|"62.151"
Q61876710|P217|"1999.171.1, .2"|P195|Q160236
Q61876710|P195|Q160236|P217|"1999.171.1, .2"
Q28732893|P217|"80.3.384"|P195|Q160236
Q28732893|P195|Q160236|P217|"80.3.384"
Q56604898|P217|"26.72.24"|P195|Q160236
Q56604898|P195|Q160236|P217|"26.72.24"
Q56604898|P217|"26.72.24"|P195|Q160236
Q56604898|P195|Q160236|P217|"26.72.24"
Q23688157|P217|"06.1322.2"|P195|Q160236
Q23688157|P195|Q160236|P217|"06.1322.2"
Q18338529|P217|"19.73.66"|P195|Q160236
Q18338529|P195|Q160236|P217|"19.73.66"
Q61876882|P217|"2003.20.4"|P195|Q160236
Q61876882|P195|Q160236|P217|"2003.20.4"
Q18339638|P217|"19.73.152"|P195|Q160236
Q18339638|P195|Q160236|P217|"19.73.152"
Q61876879|P217|"17.3.4"|P195|Q160236
Q61876879|P195|Q160236|P217|"17.3.4"
Q61781468|P217|"2009.436.1a–w"|P195|Q160236
Q61781468|P195|Q160236|P217|"2009.436.1a–w"
Q18338468|P217|"68.793.66"|P195|Q160236
Q18338468|P195|Q160236|P217|"68.793.66"
Q18338961|P217|"19.73.82"|P195|Q160236
Q18338961|P195|Q160236|P217|"19.73.82"
Q61781441|P217|"53.600.261(5)"|P195|Q160236
Q61781441|P195|Q160236|P217|"53.600.261(5)"
Q3395798|P217|"49.7.21"|P195|Q160236
Q3395798|P195|Q160236|P217|"49.7.21"
Q17275914|P217|"14.40.626–27"|P195|Q160236
Q17275914|P195|Q160236|P217|"14.40.626–27"
Q44214076|P217|"49.7.22"|P195|Q160236
Q44214076|P195|Q160236|P217|"49.7.22"
Q3094651|P217|"52.63.2"|P195|Q160236
Q3094651|P195|Q160236|P217|"52.63.2"
Q25936897|P217|"66.25"|P195|Q160236
Q25936897|P195|Q160236|P217|"66.25"
Q25936897|P217|"66.25"|P195|Q160236
Q25936897|P195|Q160236|P217|"66.25"
Q31073129|P217|"1979.317.1"|P195|Q160236
Q31073129|P195|Q160236|P217|"1979.317.1"
Q31068759|P217|"1979.317.2ab"|P195|Q160236
Q31068759|P195|Q160236|P217|"1979.317.2ab"
Q31070828|P217|"1979.317.3ab"|P195|Q160236
Q31070828|P195|Q160236|P217|"1979.317.3ab"
Q29049154|P217|"1990.38.1"|P195|Q160236
Q29049154|P195|Q160236|P217|"1990.38.1"
Q933665|P217|"1990.38.3"|P195|Q160236
Q933665|P195|Q160236|P217|"1990.38.3"
Q61884489|P217|"CTO.135"|P195|Q160236
Q61884489|P195|Q160236|P217|"CTO.135"
Q5506360|P217|"2016.237.33"|P195|Q160236
Q5506360|P195|Q160236|P217|"2016.237.33"
Q61781317|P217|"1998.456.3"|P195|Q160236
Q61781317|P195|Q160236|P217|"1998.456.3"
Q60596830|P217|"CTO.128"|P195|Q160236
Q60596830|P195|Q160236|P217|"CTO.128"
Q60517079|P217|"SL.17.2014.1.3"|P195|Q160236
Q60517079|P195|Q160236|P217|"SL.17.2014.1.3"
Q61479355|P217|"SL.17.2014.1.9"|P195|Q160236
Q61479355|P195|Q160236|P217|"SL.17.2014.1.9"
Q63082710|P217|"L.2014.77"|P195|Q160236
Q63082710|P195|Q160236|P217|"L.2014.77"
Q7107718|P217|"31.4.2"|P195|Q160236
Q7107718|P195|Q160236|P217|"31.4.2"
Q28670008|P217|"07.229.1a, b"|P195|Q160236
Q28670008|P195|Q160236|P217|"07.229.1a, b"
Q61781516|P217|"2011.599.1a"|P195|Q160236
Q61781516|P195|Q160236|P217|"2011.599.1a"
Q61627764|P217|"63.350.207.135.17"|P195|Q160236
Q61627764|P195|Q160236|P217|"63.350.207.135.17"
Q44178853|P217|"2014.520"|P195|Q160236
Q44178853|P195|Q160236|P217|"2014.520"
Q55619837|P217|"SL.1.2016.39.1"|P195|Q160236
Q55619837|P195|Q160236|P217|"SL.1.2016.39.1"
Q61781550|P217|"1972.717.1"|P195|Q160236
Q61781550|P195|Q160236|P217|"1972.717.1"
Q61781403|P217|"1972.717.4"|P195|Q160236
Q61781403|P195|Q160236|P217|"1972.717.4"
Q56651549|P217|"SL.2.2018.1.2"|P195|Q160236
Q56651549|P195|Q160236|P217|"SL.2.2018.1.2"
Q61781450|P217|"2016.113"|P195|Q160236
Q61781450|P195|Q160236|P217|"2016.113"
Q56697085|P217|"SL.2.2018.21.20"|P195|Q160236
Q56697085|P195|Q160236|P217|"SL.2.2018.21.20"
Q61781455|P217|"2018.756"|P195|Q160236
Q61781455|P195|Q160236|P217|"2018.756"