自然语言处理 - 提取数据

时间:2016-10-29 20:47:07

标签: python nltk data-extraction information-extraction

我需要帮助处理日间交易/周转交易/投资建议的非结构化数据。我以CSV

的形式提供了非结构化数据

以下是需要提取数据的3个样本段落:

  

Anand Rathi的Chandan Taparia与Coal India Ltd.有一个买入电话   日内 目标价格为338卢比当前市场   Coal India Ltd.的价格为325.15 。 Chandan Taparia建议   保持止损在318卢比

     

Kotak Securities Limited向工程师印度有限公司购买了一个   目标价格为335卢比工程师印度有限公司当前市场价格为266.05卢比分析师给工程师一年   印度有限公司的价格达到了既定目标。印度工程师喜欢   在碳氢化合物咨询部门的健康市场份额。它很享受   与少数主要石油和石油的关系多产天然气公司喜欢   HPCL,BPCL,ONGC和IOC。该公司已准备好从中受益   石油部门基础设施支出的恢复。

     

独立分析师Kunal Bothra与Ceat有限公司进行了一次销售电话会议   目标价格为1150卢比。目前Ceat有限公司的当前市场价格为1199.6卢比分析师给出的时间段 1-3天   当Ceat Ltd.的价格达到既定目标时。 Kunal Bothra   保持止损1240卢比

从段落中提取4个信息是一项挑战: 每个建议都有不同的框架,但基本上有

  1. 目标价格
  2. 止损价格
  3. 当前价格。
  4. 持续时间
  5. 并不一定所有建议中都会提供所有信息 - 每项建议至少都有目标价格

    我试图使用正则表达式,但不是很成功,任何人都可以指导我如何提取这些信息可能正在使用nltk

    代码我到目前为止清理数据:

    import pandas as pd
    import re
    
    #etanalysis_final.csv has 4 columns with 
    #0th Column having data time
    #1st Column having a simple hint like 'Sell  Ceat Ltd.  target Rs  1150  :   Kunal Bothra,Sell  Ceat Ltd.  at a price target of Rs  1150  and a stoploss at Rs  1240  from entry point', not all the hints are same, I can rely on it for recommender, Buy or Sell, which stock.
    #4th column has the detailed recommendation given.
    
    df = pd.read_csv('etanalysis_final.csv',encoding='ISO-8859-1')
    df.DATE = pd.to_datetime(df.DATE)
    df.dropna(inplace=True)
    df['RECBY'] = df['C1'].apply(lambda x: re.split(':|\x96',x)[-1].strip())
    df['ACT'] = df['C1'].apply(lambda x: x.split()[0].strip())
    df['STK'] = df['C1'].apply(lambda x: re.split('\.|\,|:| target| has| and|Buy|Sell| with',x)[1])
    #Getting the target price - not always correct
    df['TGT'] = df['C4'].apply(lambda x: re.findall('\d+.', x)[0])
    #Getting the stop loss price - not always correct
    df['STL'] = df['C4'].apply(lambda x: re.findall('\d+.\d+', x)[-1])
    

2 个答案:

答案 0 :(得分:0)

这是一个很难回答的问题,因为有四种不同的可能性可以写出4条信息。这是一种可能有用的天真方法,虽然需要验证。我将为目标做示例,但您可以将其扩展到任何目标:

CONTEXT = 6

def is_float(x):
    try:
        float(x)
        return True
    except ValueError:
        return False

def get_target_price(s):
    words = s.split()
    n = words.index('target')
    words_in_range = words[n-CONTEXT:n+CONTEXT]
    return float(list(filter(is_float, words_in_range))[0]) # returns any instance of a float

这是一个简单的方法,可以让你开始,但你可以进行额外的检查,以使这更安全。可能改进的事情:

  1. 确保找到建议的浮点数之前的索引是Rs。
  2. 如果在上下文范围内未找到浮点数,请展开上下文
  3. 如果存在歧义,即在上下文范围内有多个目标实例或多个浮点数等,则添加用户验证。

答案 1 :(得分:0)

我得到了解决方案:

此处的代码仅包含问题的解决方案部分。应该可以使用fuzzywuzzy库大大改进此解决方案。

from nltk import word_tokenize      
periods = ['year',"year's", 'day','days',"day's", 'month', "month's", 'week',"week's", 'intra-day', 'intraday']
stop = ['target', 'current', 'stop', 'period', 'stoploss']

def extractinfo(row):
    if 'intra day' in row.lower():
        row = row.lower().replace('intra day', 'intra-day')
    tks = [ w for w in word_tokenize(row) if any([w.lower() in stop, isfloat(w)])]
    tgt = ''
    crt = ''
    stp = ''
    prd = ''
    if 'target' in tks:
        if len(tks[tks.index('target'):tks.index('target')+2]) == 2:
            tgt = tks[tks.index('target'):tks.index('target')+2][-1]
    if 'current' in tks:
        if len(tks[tks.index('current'):tks.index('current')+2]) == 2:
            crt = tks[tks.index('current'):tks.index('current')+2][-1]
    if 'stop' in tks:
        if len(tks[tks.index('stop'):tks.index('stop')+2]) == 2:
            stp = tks[tks.index('stop'):tks.index('stop')+2][-1]
    prdd = set(periods).intersection(tks)       
    if 'period' in tks:
        pdd = tks[tks.index('period'):tks.index('period')+3]
        prr = set(periods).intersection(pdd)
        if len(prr) > 0:
            if len(pdd) > 2:
                prd = ' '.join(pdd[-2::1])
            elif len(pdd) == 2:
                prd = pdd[-1]
    elif len(prdd) > 0:
        prd = list(prdd)[0]
    return (crt, tgt, stp, prd)

解决方案相对自我解释 - 其他请告诉我。