Conjunto de dados de investigação aberta COVID-19

Conjunto de dados de texto completo e metadados de artigos académicos sobre a COVID-19 e relacionados com o coronavírus otimizados para legibilidade automática e disponibilizados para utilização pela comunidade de investigação global.

Em resposta à pandemia COVID-19, o Allen Institute for AI estabeleceu uma parceria com os principais grupos de investigação para preparar e distribuir o Conjunto de Dados de Investigação Aberta COVID-19 (CORD-19). Este conjunto de dados é um recurso gratuito de mais de 47.000 artigos eruditos, incluindo mais de 36.000 com texto completo, sobre o COVID-19 e a família coronavírus de vírus para uso pela comunidade de pesquisa global.

Este conjunto de dados mobiliza os investigadores para aplicar os recentes avanços no processamento de linguagem natural para gerar novos conhecimentos de apoio à luta contra esta doença infeciosa.

O corpus poderá ser atualizado à medida que a nova investigação é publicada em publicações revistas por colegas e serviços de arquivo como o bioRxiv, medRxiv, entre outros.

Nota

A Microsoft fornece conjuntos de dados Azure Open numa base "ase". A Microsoft não oferece garantias, expressas ou implícitas, garantias ou condições relativas à utilização dos conjuntos de dados. Na medida do permitido pela sua legislação local, a Microsoft declina toda a responsabilidade por quaisquer danos ou perdas, incluindo danos ou perdas diretas, consequentes, especiais, indiretos, incidentais ou punitivas, resultantes da utilização dos conjuntos de dados.

Este conjunto de dados é disponibilizado de acordo com os termos originais em que a Microsoft recebeu os dados de origem. O conjunto de dados pode incluir dados obtidos junto da Microsoft.

Termos de Licenciamento

Este conjunto de dados é disponibilizado pelo Allen Institute of AI e pelo Académico Semântico. Ao aceder, transferir ou utilizar algum conteúdo fornecido no Conjunto de Dados CORD-19, concorda com a Licença de Conjunto de Dados referente à utilização deste conjunto de dados. As informações de licenciamento específicas de artigos individuais no conjunto de dados estão disponíveis no ficheiro de metadados. Mais informações sobre licenciamento estão disponíveis no site da PMC, no site da MedRxive no site da bioRxiv.

Volume e retenção

Este conjunto de dados é armazenado em formato JSON e a versão mais recente contém mais de 36.000 artigos de texto completos. Cada documento é representado por um único objeto JSON. Ver o esquema.

Localização do Armazenamento

Este conjunto de dados é armazenado na região do Azure E.U.A. Leste. A localização de recursos computacional nos EUA orientais é recomendada para afinidade.

Citação

Ao incluir os dados DO CORD-19 numa publicação ou redistribuição, cite o conjunto de dados da seguinte forma:

Na bibliografia:

COVID-19 Open Research Dataset (CORD-19). 2020. Versão AAAA-MM-DD. Retirado do COVID-19 Open Research Dataset (CORD-19). Acedido em AAAA-MM-DD. doi:10.5281/zenodo.3715505

No texto: (CORD-19, 2020)

Contacto

Para colocar questões sobre este conjunto de dados, contacte partnerships@allenai.org.

Acesso a dados

Azure Notebooks

O conjunto de dados CORD-19

CORD-19 é uma coleção de mais de 50.000 artigos eruditos - incluindo mais de 40.000 com texto completo - sobre COVID-19, SARS-CoV-2, e vírus corona relacionados. Este conjunto de dados foi disponibilizado livremente com o objetivo de ajudar as comunidades de investigação a combater a pandemia COVID-19.

O objetivo deste caderno é duplo:

  1. Demonstrar como aceder ao conjunto de dados CORD-19 no Azure: Ligamos à conta de armazenamento de blob Azure que alberga o conjunto de dados CORD-19.
  2. Caminhe embora a estrutura do conjunto de dados: Os artigos no conjunto de dados são armazenados como ficheiros json. Fornecemos exemplos que mostram:
  • Como encontrar os artigos (navegando no recipiente)
  • Como ler os artigos (navegando no esquema json)

Dependências: Este caderno requer as seguintes bibliotecas:

  • Armazenamento Azure (por exemplo, pip install azure-storage )
  • NLTK(docs)
  • Pandas (por exemplo, pip install pandas )

Obtenção dos dados do CORD-19 do Azure

Os dados CORD-19 foram enviados como um conjunto de dados abertos do Azure aqui. Criamos um serviço blob ligado a este conjunto de dados aberto CORD-19.

from azure.storage.blob import BlockBlobService

# storage account details
azure_storage_account_name = "azureopendatastorage"
azure_storage_sas_token = "sv=2019-02-02&ss=bfqt&srt=sco&sp=rlcup&se=2025-04-14T00:21:16Z&st=2020-04-13T16:21:16Z&spr=https&sig=JgwLYbdGruHxRYTpr5dxfJqobKbhGap8WUtKFadcivQ%3D"

# create a blob service
blob_service = BlockBlobService(
    account_name=azure_storage_account_name,
    sas_token=azure_storage_sas_token,
)

Podemos usar este serviço blob como uma pega nos dados. Podemos navegar no conjunto de dados que utiliza as BlockBlobService APIs. Consulte aqui mais detalhes:

Os dados CORD-19 são armazenados no covid19temp recipiente. Esta é a estrutura do ficheiro dentro do recipiente juntamente com um ficheiro de exemplo.

metadata.csv
custom_license/
    pdf_json/
        0001418189999fea7f7cbe3e82703d71c85a6fe5.json        # filename is sha-hash
        ...
    pmc_json/
        PMC1065028.xml.json                                  # filename is the PMC ID
        ...
noncomm_use_subset/
    pdf_json/
        0036b28fddf7e93da0970303672934ea2f9944e7.json
        ...
    pmc_json/
        PMC1616946.xml.json
        ...
comm_use_subset/
    pdf_json/
        000b7d1517ceebb34e1e3e817695b6de03e2fa78.json
        ...
    pmc_json/
        PMC1054884.xml.json
        ...
biorxiv_medrxiv/                                             # note: there is no pmc_json subdir
    pdf_json/
        0015023cc06b5362d332b3baf348d11567ca2fbb.json
        ...

Cada ficheiro .json corresponde a um artigo individual no conjunto de dados. É aqui que o título, autores, resumo e (quando disponível) os dados completos do texto são armazenados.

Usando metadata.csv

O conjunto de dados CORD-19 vem com metadata.csv - um único ficheiro que regista informações básicas em todos os documentos disponíveis no conjunto de dados CORD-19. Este é um bom lugar para começar a explorar!

# container housing CORD-19 data
container_name = "covid19temp"

# download metadata.csv
metadata_filename = 'metadata.csv'
blob_service.get_blob_to_path(
    container_name=container_name,
    blob_name=metadata_filename,
    file_path=metadata_filename
)
import pandas as pd

# read metadata.csv into a dataframe
metadata_filename = 'metadata.csv'
metadata = pd.read_csv(metadata_filename)
metadata.head(3)

É muito para aceitar à primeira vista, então vamos aplicar um pouco de polimento.

simple_schema = ['cord_uid', 'source_x', 'title', 'abstract', 'authors', 'full_text_file', 'url']

def make_clickable(address):
    '''Make the url clickable'''
    return '<a href="{0}">{0}</a>'.format(address)

def preview(text):
    '''Show only a preview of the text data.'''
    return text[:30] + '...'

format_ = {'title': preview, 'abstract': preview, 'authors': preview, 'url': make_clickable}

metadata[simple_schema].head().style.format(format_)
# let's take a quick look around
num_entries = len(metadata)
print("There are {} many entries in this dataset:".format(num_entries))

metadata_with_text = metadata[metadata['full_text_file'].isna() == False]
with_full_text = len(metadata_with_text)
print("-- {} have full text entries".format(with_full_text))

with_doi = metadata['doi'].count()
print("-- {} have DOIs".format(with_doi))

with_pmcid = metadata['pmcid'].count()
print("-- {} have PubMed Central (PMC) ids".format(with_pmcid))

with_microsoft_id = metadata['Microsoft Academic Paper ID'].count()
print("-- {} have Microsoft Academic paper ids".format(with_microsoft_id))
There are 51078 many entries in this dataset:
-- 42511 have full text entries
-- 47741 have DOIs
-- 41082 have PubMed Central (PMC) ids
-- 964 have Microsoft Academic paper ids

Exemplo: Ler texto completo

metadata.csv não contém o texto completo em si. Vamos ver um exemplo de como ler isto. Localize e desembale o texto completo e converta-o numa lista de frases.

# choose a random example with pdf parse available
metadata_with_pdf_parse = metadata[metadata['has_pdf_parse']]
example_entry = metadata_with_pdf_parse.iloc[42]

# construct path to blob containing full text
blob_name = '{0}/pdf_json/{1}.json'.format(example_entry['full_text_file'], example_entry['sha'])  # note the repetition in the path
print("Full text blob for this entry:")
print(blob_name)

Agora podemos ler o conteúdo json associado a esta bolha da seguinte forma.

import json
blob_as_json_string = blob_service.get_blob_to_text(container_name=container_name, blob_name=blob_name)
data = json.loads(blob_as_json_string.content)

# in addition to the body text, the metadata is also stored within the individual json files
print("Keys within data:", ', '.join(data.keys()))

Para efeitos deste exemplo, estamos interessados no body_text , que armazena os dados de texto da seguinte forma:

"body_text": [                      # list of paragraphs in full body
    {
        "text": <str>,
        "cite_spans": [             # list of character indices of inline citations
                                    # e.g. citation "[7]" occurs at positions 151-154 in "text"
                                    #      linked to bibliography entry BIBREF3
            {
                "start": 151,
                "end": 154,
                "text": "[7]",
                "ref_id": "BIBREF3"
            },
            ...
        ],
        "ref_spans": <list of dicts similar to cite_spans>,     # e.g. inline reference to "Table 1"
        "section": "Abstract"
    },
    ...
]

O esquema completo json está disponível aqui.

from nltk.tokenize import sent_tokenize

# the text itself lives under 'body_text'
text = data['body_text']

# many NLP tasks play nicely with a list of sentences
sentences = []
for paragraph in text:
    sentences.extend(sent_tokenize(paragraph['text']))

print("An example sentence:", sentences[0])

PDF vs PMC XML Parse

No exemplo acima, analisámos um caso has_pdf_parse == True com. Nesse caso, o caminho do ficheiro blob era do formulário:

'<full_text_file>/pdf_json/<sha>.json'

Alternativamente, para casos com has_pmc_xml_parse == True utilização do seguinte formato:

'<full_text_file>/pmc_json/<pmcid>.xml.json'

Por exemplo:

# choose a random example with pmc parse available
metadata_with_pmc_parse = metadata[metadata['has_pmc_xml_parse']]
example_entry = metadata_with_pmc_parse.iloc[42]

# construct path to blob containing full text
blob_name = '{0}/pmc_json/{1}.xml.json'.format(example_entry['full_text_file'], example_entry['pmcid'])  # note the repetition in the path
print("Full text blob for this entry:")
print(blob_name)

blob_as_json_string = blob_service.get_blob_to_text(container_name=container_name, blob_name=blob_name)
data = json.loads(blob_as_json_string.content)

# the text itself lives under 'body_text'
text = data['body_text']

# many NLP tasks play nicely with a list of sentences
sentences = []
for paragraph in text:
    sentences.extend(sent_tokenize(paragraph['text']))

print("An example sentence:", sentences[0])
Full text blob for this entry:
custom_license/pmc_json/PMC546170.xml.json
An example sentence: Double-stranded small interfering RNA (siRNA) molecules have drawn much attention since it was unambiguously shown that they mediate potent gene knock-down in a variety of mammalian cells (1).

Iterar através de bolhas diretamente

Nos exemplos acima, usamos o metadata.csv ficheiro para navegar os dados, construir o caminho do ficheiro blob e ler dados a partir da bolha. Uma alternativa é a iterada através das próprias bolhas.

# get and sort list of available blobs
blobs = blob_service.list_blobs(container_name)
sorted_blobs = sorted(list(blobs), key=lambda e: e.name, reverse=True)

Agora podemos iterar diretamente através das bolhas. Por exemplo, vamos contar os ficheiros json números disponíveis.

# we can now iterate directly though the blobs
count = 0
for blob in sorted_blobs:
    if blob.name[-5:] == ".json":
        count += 1
print("There are {} many json files".format(count))
There are 59784 many json files

Apêndice

Questões de qualidade dos dados

Trata-se de um conjunto de dados de grande enquanto que, por razões óbvias, foi montado apressadamente! Aqui estão alguns problemas de qualidade de dados que observamos.

Várias shas

Observamos que em alguns casos há várias shas para uma determinada entrada.

metadata_multiple_shas = metadata[metadata['sha'].str.len() > 40]

print("There are {} many entries with multiple shas".format(len(metadata_multiple_shas)))

metadata_multiple_shas.head(3)
There are 1999 many entries with multiple shas

Disposição do recipiente

Aqui usamos um regex simples para explorar a estrutura de arquivo do recipiente no caso de este ser atualizado no futuro.

container_name = "covid19temp"
blobs = blob_service.list_blobs(container_name)
sorted_blobs = sorted(list(blobs), key=lambda e: e.name, reverse=True)
import re
dirs = {}

pattern = '([\w]+)\/([\w]+)\/([\w.]+).json'
for blob in sorted_blobs:
    
    m = re.match(pattern, blob.name)
    
    if m:
        dir_ = m[1] + '/' + m[2]
        
        if dir_ in dirs:
            dirs[dir_] += 1
        else:
            dirs[dir_] = 1
        
dirs

Passos seguintes

Ver o resto dos conjuntos de dados no catálogo Open Datasets.