2010-10-25 2 views
13

Я медсестра, и я знаю python, но я не эксперт, просто использовал его для обработки последовательностей ДНК.
Мы получили записи о больницах, написанные на человеческих языках, и я должен вставить эти данные в база данных или CSV-файл, но они более 5000 строк, и это может быть так сложно. Все данные записываются в последовательном формате, позвольте мне показать вам примерИзвлечение медицинской информации с использованием Python

11/11/2010 - 09:00am : He got nausea, vomiting and died 4 hours later 

я должен получить следующие данные

Sex: Male 
Symptoms: Nausea 
    Vomiting 
Death: True 
Death Time: 11/11/2010 - 01:00pm 

Другой пример

11/11/2010 - 09:00am : She got heart burn, vomiting of blood and died 1 hours later in the operation room 

И я получаю

Sex: Female 
Symptoms: Heart burn 
    Vomiting of blood 
Death: True 
Death Time: 11/11/2010 - 10:00am 

th e order не согласуется с тем, когда я говорю в ......., поэтому in - это ключевое слово, и весь текст после этого места, пока я не найду другое ключевое слово
В начале он или она определяет секс, получил ... ..... все, что следует, это группа симптомов, которые я должен разделить в соответствии с разделителем, который может быть запятой, гипной или чем-то другим, но он согласован для одной и той же линии.
умер ..... спустя несколько часов также должен быть много часов, иногда пациент остается жив и разряжен .... и т. д.
То есть у нас есть много соглашений, и я думаю, что если я смогу подделать текст с помощью ключевых слов и шаблонов, я смогу выполнить эту работу. Поэтому, пожалуйста, если вы знаете, полезную функцию/модули/учебник/инструмент для делать это желательно в Python (если не Python так инструмент графического интерфейса было бы неплохо)

Некоторые мало информации:

there are a lot of rules to express various medical data but here are few examples 
- Start with the same date/time format followed by a space followd by a colon followed by a space followed by He/She followed space followed by rules separated by and 
- Rules: 
    * got <symptoms>,<symptoms>,.... 
    * investigations were done <investigation>,<investigation>,<investigation>,...... 
    * received <drug or procedure>,<drug or procedure>,..... 
    * discharged <digit> (hour|hours) later 
    * kept under observation 
    * died <digit> (hour|hours) later 
    * died <digit> (hour|hours) later in <place> 
other rules do exist but they follow the same idea 
+3

Это может быть полезно, если вы можете привести еще несколько примеров, в том числе тех, где существуют разные заказы, или когда пациент живет/выписан. – GWW

+1

Есть ли список ключевых слов, которые являются допустимыми симптомами? Будут ли все записи начинаться с «он» или «она»? Все ли записи начинаются с даты/времени в том же формате? Если пациент выписан, будет ли в записи всегда слово «разряжено», а затем «х часов спустя»? – philosodad

+0

ok Я добавил немного информации в нижней части вопроса. – Nurse

ответ

9

Это использует dateutil разобрать дату (например, '11/11/2010 - 09:00 am '), и parsedatetime для синтаксического анализа относительного времени (например, '4 часа'):

import dateutil.parser as dparser 
import parsedatetime.parsedatetime as pdt 
import parsedatetime.parsedatetime_consts as pdc 
import time 
import datetime 
import re 
import pprint 
pdt_parser = pdt.Calendar(pdc.Constants()) 
record_time_pat=re.compile(r'^(.+)\s+:') 
sex_pat=re.compile(r'\b(he|she)\b',re.IGNORECASE) 
death_time_pat=re.compile(r'died\s+(.+hours later).*$',re.IGNORECASE) 
symptom_pat=re.compile(r'[,-]') 

def parse_record(astr):  
    match=record_time_pat.match(astr) 
    if match: 
     record_time=dparser.parse(match.group(1)) 
     astr,_=record_time_pat.subn('',astr,1) 
    else: sys.exit('Can not find record time') 
    match=sex_pat.search(astr)  
    if match: 
     sex=match.group(1) 
     sex='Female' if sex.lower().startswith('s') else 'Male' 
     astr,_=sex_pat.subn('',astr,1) 
    else: sys.exit('Can not find sex') 
    match=death_time_pat.search(astr) 
    if match: 
     death_time,date_type=pdt_parser.parse(match.group(1),record_time) 
     if date_type==2: 
      death_time=datetime.datetime.fromtimestamp(
       time.mktime(death_time)) 
     astr,_=death_time_pat.subn('',astr,1) 
     is_dead=True 
    else: 
     death_time=None 
     is_dead=False 
    astr=astr.replace('and','')  
    symptoms=[s.strip() for s in symptom_pat.split(astr)] 
    return {'Record Time': record_time, 
      'Sex': sex, 
      'Death Time':death_time, 
      'Symptoms': symptoms, 
      'Death':is_dead} 


if __name__=='__main__': 
    tests=[('11/11/2010 - 09:00am : He got nausea, vomiting and died 4 hours later', 
      {'Sex':'Male', 
      'Symptoms':['got nausea', 'vomiting'], 
      'Death':True, 
      'Death Time':datetime.datetime(2010, 11, 11, 13, 0), 
      'Record Time':datetime.datetime(2010, 11, 11, 9, 0)}), 
      ('11/11/2010 - 09:00am : She got heart burn, vomiting of blood and died 1 hours later in the operation room', 
      {'Sex':'Female', 
      'Symptoms':['got heart burn', 'vomiting of blood'], 
      'Death':True, 
      'Death Time':datetime.datetime(2010, 11, 11, 10, 0), 
      'Record Time':datetime.datetime(2010, 11, 11, 9, 0)}) 
      ] 

    for record,answer in tests: 
     result=parse_record(record) 
     pprint.pprint(result) 
     assert result==answer 
     print 

урожаи :

{'Death': True, 
'Death Time': datetime.datetime(2010, 11, 11, 13, 0), 
'Record Time': datetime.datetime(2010, 11, 11, 9, 0), 
'Sex': 'Male', 
'Symptoms': ['got nausea', 'vomiting']} 

{'Death': True, 
'Death Time': datetime.datetime(2010, 11, 11, 10, 0), 
'Record Time': datetime.datetime(2010, 11, 11, 9, 0), 
'Sex': 'Female', 
'Symptoms': ['got heart burn', 'vomiting of blood']} 

Примечание: будьте внимательны к датам синтаксического анализа. «8/9/2010» означает 9 августа или 8 сентября? Используют ли все хранители записей одно и то же соглашение? Если вы решите использовать dateutil (и я действительно считаю, что это лучший вариант, если строка даты не жестко структурирована), обязательно прочитайте раздел «Формат приоритета» в dateutil documentation, чтобы вы могли (надеюсь) решить «8/9/2010 ». Если вы не можете гарантировать, что все хранители записей используют одно и то же соглашение для указания дат, результаты этого скрипта будут проверяться вручную. В любом случае это может быть разумным.

+2

+1 Just для того, чтобы сделать все это. –

9

Вот некоторые возможно, как вы можете решить эту проблему -

  1. Использование регулярных выражений - Определить их в соответствии с шаблонами в тексте. Сопоставьте выражения, извлеките шаблон и повторите все записи. Этот подход требует хорошего понимания формата, в котором данные &, конечно, регулярных выражений :)
  2. String Manipulation - Этот подход относительно прост. Опять же нужно хорошее понимание формата, в котором данные. Это то, что я сделал ниже.
  3. Machine Learning - Вы можете определить все, что вы делаете, & подготовить модель по этим правилам. После этого модель пытается извлечь данные, используя предоставленные вами правила. Это гораздо более общий подход, чем первые два. Также сложнее реализовать.

Посмотрите, подходит ли эта работа для вас. Могут потребоваться некоторые корректировки.

new_file = open('parsed_file', 'w') 
for rec in open("your_csv_file"): 
    tmp = rec.split(' : ') 
    date = tmp[0] 
    reason = tmp[1] 

    if reason[:2] == 'He': 
     sex = 'Male' 
     symptoms = reason.split(' and ')[0].split('He got ')[1] 
    else: 
     sex = 'Female' 
     symptoms = reason.split(' and ')[0].split('She got ')[1] 
    symptoms = [i.strip() for i in symptoms.split(',')] 
    symptoms = '\n'.join(symptoms) 
    if 'died' in rec: 
     died = 'True' 
    else: 
     died = 'False' 
    new_file.write("Sex: %s\nSymptoms: %s\nDeath: %s\nDeath Time: %s\n\n" % (sex, symptoms, died, date)) 

Ech запись новой строки разделены \n &, так как вы не упомянул один запись пациента 2 перевода строки отделены \n\n от другого.

LATER: @Nurse какой вы в конечном итоге делаете? Просто любопытно.

+0

Я как раз собирался прокомментировать и сказать в основном это: он выглядит как 'string.split (...)', и простой конечный автомат (например, этот) даст вам наибольшую выгоду для вашего доллара. –

+0

это про это. Основные строчки. Если ваши записи находятся в шаблоне, вы говорите, что они есть. Тогда это должно работать из коробки. Но если возникают некоторые несоответствия (поскольку я не знаю данных).Возможно, вам придется немного подстроить его для соответствия вашим данным. –

+0

Я бы сделал это так, если это согласовано. Есть много правил, и они не существуют в том же порядке. Мы не можем обработать его линеари, если вы знаете, что я имею в виду. – Nurse

3

Может быть, это может помочь вам тоже, это не тестировалось

import collections 
import datetime 
import re 

retrieved_data = [] 

Data = collections.namedtuple('Patient', 'Sex, Symptoms, Death, Death_Time') 
dict_data = {'Death':'', 
      'Death_Time':'', 
      'Sex' :'', 
      'Symptoms':''} 


with open('data.txt') as f: 
    for line in iter(f.readline, ""): 

     date, text = line.split(" : ") 
     if 'died' in text: 
      dict_data['Death'] = True 
      dict_data['Death_Time'] = datetime.datetime.strptime(date, 
                   '%d/%m/%Y - %I:%M%p') 
      hours = re.findall('[\d]+', datetime.text) 
      if hours: 
       dict_data['Death_Time'] += datetime.timedelta(hours=int(hours[0])) 
     if 'she' in text: 
      dict_data['Sex'] = 'Female' 
     else: 
      dict_data['Sex'] = 'Male' 

     symptoms = text[text.index('got'):text.index('and')].split(',') 

     dict_data['Symptoms'] = '\n'.join(symptoms) 

     retrieved_data.append(Data(**dict_data)) 

     # EDIT : Reset the data dictionary. 
     dict_data = {'Death':'', 
      'Death_Time':'', 
      'Sex' :'', 
      'Symptoms':''} 
1

Было бы относительно легко сделать большую часть обработки в отношении пола, даты/времени и т.д., как и перед вами показали , так как вы действительно можете просто определить набор ключевых слов, которые будут указывать на эти вещи и использовать эти ключевые слова.

Однако проблема обработки симптомов несколько отличается, поскольку окончательный список ключевых слов, представляющих симптомы, будет затруднен и, скорее всего, невозможно.

Вот выбор, который вы должны сделать: обрабатывает ли эти данные действительно достаточную работу, чтобы потратить дни, написав программу, чтобы сделать это для меня? Если это так, то вам следует изучить обработку естественного языка (или машинное обучение, как сказал кто-то, кто передо мной). Я слышал о хороших вещах о nltk, наборе инструментов для естественного языка для Python. Если формат такой же последовательный, как вы говорите, обработка естественного языка может быть не слишком сложной.

Но если вы не хотите тратить время и силы на решение действительно сложной проблемы CS (и, поверьте, обработка на естественном языке), тогда вы должны выполнить большую часть обработки на Python, проанализировав даты , местоимения, специфичные для пола, и т. д. и вводятся в более жесткие части вручную (например, симптомы).

Опять же, это зависит от того, считаете ли вы, что программное или ручное решение займет меньше времени в долгосрочной перспективе.

+0

, но если я понимаю формат, симптомами будут только любые очерченные строки между ключевым словом «got» и next »и« – philosodad

+0

Надеюсь, это правда, и в этом случае вы могли бы просто использовать нормальный строковая обработка или повторная GEX. –

+0

Это то, что я искал. Я уже пробовал nltk, но документация очень технична, и я не могу ее получить. На самом деле я не против потратить месяц или два на разработку инструмента, который поможет мне в долгосрочной перспективе. У меня есть около 7000-10000 записей, которые нужно вставлять в базу данных каждый месяц, поэтому инвестирование времени обучения не будет пустой тратой времени. – Nurse

Смежные вопросы