蟒蛇。从文本文件获取数据并放入数据框

时间:2018-07-07 09:31:43

标签: python

我有一个包含文本和数据的txt文件。我想获取州名,年份,所有捐助者类型,已故捐助者,活体捐助者。 该文件包含状态级别捐赠面板数据。我想摆脱所有捐助者状态数据的第一时间序列,摆脱说明文本,找到状态名称时,摆脱状态名称之后该状态的捐赠数据的To date聚合级别,收集从年份开始的年度捐赠数据,请在年度数据之前加上州名称。 Unitll有一个新的州名称,说明文字后的年度数据属于最后一个州。

            All Donor Types Deceased Donor  Living Donor
 All Donor States of Residence   To Date        360,673 205,858 154,815
     2018       7,107   4,394   2,713
     2017       16,478  10,286  6,192
     2016       15,944  9,971   5,973
     2015       15,071  9,079   5,992
     2014       14,415  8,596   5,819
Data subject to change based on future data submission or correction.
Donor : Donor Type by Donor State of Residence, Donation Year   Page 2 of 70
Donors Recovered : January 1, 1988 - May 31, 2018
For Format = Landscape
Based on OPTN data as of July 4, 2018

            All Donor Types Deceased Donor  Living Donor
     1993       7,766   4,861   2,905
     1992       7,091   4,520   2,571
 Alabama     To Date        5,926   3,471   2,455
     2018       95  65  30
     2017       259 172 87
     2016       249 175 74
 Alaska  To Date        935 565 370
     2018       14  9   5
     2017       42  32  10
     2016       30  22  8
Data subject to change based on future data submission or correction.
Donor : Donor Type by Donor State of Residence, Donation Year   Page 70 of 70
Donors Recovered : January 1, 1988 - May 31, 2018
For Format = Landscape
Based on OPTN data as of July 4, 2018

            All Donor Types Deceased Donor  Living Donor
     1989       16  12  4
     1988       16  11  5

我想获取州名称阿拉巴马州和阿拉斯加之后的年度数据,删除文本,所有州捐赠数据的第一组以及每个州名称之后的“ To Date”聚合值。 最后,我要

state year all deceased living
Alabama 2018 95 65 30
Alabama 2017 259 172 87
Alabama 2016 249 175 74
Alaska 2018 14  9 5
Alaska 2017 42 32 10
Alaska 2016 30  22  8
Alaska 1989  16 12  4
Alaska 1988  16 11  5

我尝试了很多,代码

import pandas as pd
fname = "optn.txt"
fh = open(fname)
count = 0
state=['Alabama','Alaska','Arizona','Arkansas',
'California','Colorado','Connecticut','Delaware',
'District of Columbia','Florida']
year=['2018','2017','2016','2015','2014','2013','2012',
'2011','2010','2009','2008','2007','2006','2005','2004',
'2003','2002','2001','2000','1999','1998','1997','1996',
'1995','1994','1993','1992','1991','1990','1989','1988']
optny=list()
for line in fh:
    line = line.strip()
    #print(line)
    if not line.startswith(tuple(year)):continue
    optny.append(line)
    #break
print(optny)

到目前为止,我可以获取以州名或年份开头的所有行,并将它们放入名为optny的列表中。我可以将清单打印出来。该列表包含所有状态数据,以及应该删除的“迄今为止”聚合数据。我想将其放入数据帧中,然后删除无用的数据,并将状态名称添加到每一行。仍无法实现。

谢谢。

1 个答案:

答案 0 :(得分:0)

这似乎是一项需要使用正则表达式的任务。

请注意,对于当前的解决方案,格式必须与示例中的格式相同。

首先,确定不必要的字符串

import re

clean_pattern = re.compile(
    r"(^[A-Z].+)|All Donor Types Deceased Donor  Living Donor", 
    re.MULTILINE
)

此模式匹配以大写字母开头的行,例如“数据主题...”,但忽略以空格开头(例如后跟其他字符)的行。第二部分也与“所有供体类型...”行匹配。

接下来,使用以下模式查找状态和表内容

state_pattern = re.compile(
    r"^\s+(?P<state>[a-zA-Z]+)\s+To Date[0-9, ]+\n(?P<content>[0-9, \n]+)$", 
    re.MULTILINE
) 

现在,我假设状态仅由一个单词组成,它们是句子中的第一个单词,后跟“ To Date”。另外,由于文本是事先清除的,因此它应该只包含数字和逗号之外的数据。接下来的单词将形成不同的状态/内容条目。

最后但并非最不重要的一点是,定义数据模式

data_pattern = re.compile(
    r"(?P<year>[0-9]{4})\s+(?P<all>[0-9,]+)\s+(?P<deceased>[0-9,]+)\s+(?P<living>[0-9,]+)"
)

已经定义了模式,现在可以提取数据(假设全文存储在text中)

data = []
# remove the unwanted lines
cleaned_text = clean_pattern.sub('', text)
# iterate over state / content matches
for state_match in state_pattern.finditer(cleaned_text):
    info_dict = state_match.groupdict()
    # iterate over data matches
    for match in data_pattern.finditer(info_dict['content']):
        data_dict = match.groupdict()
        # add the state information to the data
        data_dict['state'] = info_dict['state']
        data.append(data_dict)

pd.DataFrame(data, columns=['state', 'year', 'all', 'deceased', 'living'])