14

私は看護師でPythonを知っていますが、専門家ではなく、DNA配列
を処理するために使用しました。人間の言語で書かれた病院の記録を取得し、これらのデータをデータベースまたはcsvファイルに挿入することになっていますが、5000を超えています行とこれはとても難しいことができます。すべてのデータは一貫した形式で書かれています例を示しましょう

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

私が.......で言うとき、順序は一貫していません。したがって、inはキーワードであり、その後のすべてのテキストは、別のキーワードが見つかるまでの場所です
。 ...以下は、コンマ、ハイフンなどの区切り文字に従って分割する必要がある一連の症状ですが、同じ行が死んだ場合でも一貫しています
.....数時間後も、場合によっては何時間かかるはずです。患者はまだ生きていて退院しています....etc
つまり、私たちにはたくさんの慣習があり、キーワードとパターンでテキストをトークン化できれば、仕事を成し遂げることができると思います。したがって、Pythonでそれを行うための便利な関数/モジュール/チュートリアル/ツールを知っている場合はお願いします(Pythonでない場合はGUIツールがいいでしょう)

いくつかの情報:

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
4

4 に答える 4

9

これを解決するためのいくつかの可能な方法があります-

  1. 正規表現の使用-テキストのパターンに従って正規表現を定義します。式を一致させ、パターンを抽出すると、すべてのレコードに対して繰り返します。このアプローチでは、データが正規表現である形式を十分に理解する必要があります:)
  2. 文字列操作-このアプローチは比較的簡単です。ここでも、データの形式をよく理解する必要があります。これは私が以下で行ったことです。
  3. 機械学習-すべてのルールを定義し、これらのルールでモデルをトレーニングできます。この後、モデルは指定されたルールを使用してデータを抽出しようとします。これは、最初の2つよりもはるかに一般的なアプローチです。また、実装するのが最も困難です。

これがあなたのために働くかどうか見てください。調整が必要な場合があります。

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ています。1つの患者レコードについて言及しなかったため、2つの改行\n\nが他のレコードから分離されています。

後で: @Nurseあなたは何をすることになったのですか?ちょっと興味があるんだけど。

于 2010-10-25T02:47:36.600 に答える
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']}

注:日付の解析には注意してください。「2010年8月9日」は8月9日または9月8日を意味しますか?すべてのレコードキーパーは同じ規則を使用していますか?dateutilを使用することを選択した場合(日付文字列が厳密に構造化されていない場合は、これが最善のオプションだと思います)、dateutilドキュメントの「フォーマットの優先順位」のセクションを読んで、 (うまくいけば)'8/9を解決できるようにしてください。 /2010'正しく。すべてのレコードキーパーが日付の指定に同じ規則を使用することを保証できない場合は、このスクリプトの結果を手動でチェックする必要があります。いずれにせよ、それは賢明かもしれません。

于 2010-10-25T03:36:51.003 に答える
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':''}
于 2010-10-25T04:11:09.847 に答える
1

性別、日付/時刻などに関しては、前に示したように、これらのことを示す一連のキーワードを定義してそれらのキーワードを使用できるため、ほとんどの処理を比較的簡単に行うことができます。

ただし、症状を表すキーワードの明確なリストは困難であり、おそらく不可能であるため、症状の処理の問題は少し異なります。

これがあなたがしなければならない選択です:このデータを処理することは本当に私のためにそれをするためのプログラムを書くのに何日も費やすのに十分な仕事を表していますか?その場合は、自然言語処理(または私の前の誰かが言ったように機械学習)を調べる必要があります。Python用の自然言語ツールキットであるnltkについてはかなり良いことを聞いたことがあります。あなたが言うようにフォーマットが一貫していれば、自然言語処理はそれほど難しくないかもしれません。

しかし、本当に難しいCSの問題に取り組むために時間と労力を費やしたくない場合(そして私を信じて、自然言語処理はそうです)、性別固有の日付を解析することによって、Pythonでほとんどの処理を行う必要があります代名詞など、手で難しい部分に入力します(例:症状)。

繰り返しになりますが、それは、プログラムまたは手動のソリューションが長期的にはより短い時間で済むと思うかどうかによって異なります。

于 2010-10-25T04:45:09.553 に答える