简体   繁体   中英

How to parse values from a text file into a list, while filling missing values with None?

  • I have a text file of raw data I am parsing.
  • There are certain codes in there that indicate the field.
  • These values will go into lists that then go into dataframe in pandas and eventually a database

For example a small portion with 2 records looks like:

INS*Y*18*001*AL*A*E**AC**N~
REF*1L*690553677~
DTP*348*D8*20200601~
DTP*349*D8*20200630~
HD*024**FAC*KJ/165/////1M*IND~
INS*Y*18*001*AL*A*E**AC**N~
REF*1L*6905456455~
DTP*348*D8*20200601~
HD*024**FAC*KJ/165/////1M*IND~
  • "DTP" indicates a date, and 348 means a start_date and 349 indicates an end_date .
  • Each group of line corresponds to a member in membership data.
    • The "REF" is the line with the Members membership number.
    • "INS" indicates its a new member or record in the database.
    • Some members don't have an end_date line "DTP*349" like our second record.
      • These should append to the end_date list with "" to hold a place as a null
  • While looping through each line, look for where the line starts with the code I want, and splits the line, and takes the specified element.
  • How do I account for where a certain field is missing in the loop, so that if a member has an end_date or not, there will be a value in that members index place, so it can all be put in a pandas dataframe?

My code thus far look like:

membership_type=[]
member_id=[]
startDate = []
endDate = []
with open(path2 + fileName, "r") as txtfile:
    for line in txtfile:
        # Member type
        if line.startswith("INS*"):
            line.split("*")
            membership_type.extend(line[4]
        # Member ID
        if line.startwith("REF*"):
            line.split("*")
            member_id.extend(line[2])
        # Start Dates
        if line.startswith("DTP*348*"):
            line = line.split("*")
            start_date.extend(line[3])
        # End Dates
        '''What goes here?'''

Results should look like:

print(membership_type)
['AL','AL']
print(member_id)
['690553677','690545645']
print(startDate)
['20200601','20200601']
print(endDate)
['20200630','']
  • Every record will have a INS and REF and HD field
  • Use readlines to get all the rows of strings
    • Clean rows of text and then use re.split to split on multiple items, * and / in this case.
    • Splitting on / will properly separate unique items in the string, but will also create blank spaces to be removed.
    • Use enumerate on each row
      • With the entire list of rows, you can see the current index, i , but i + or - a number can be used to also compare a different row.
      • If the next row after DTP 348 isn't DTP, then add None or '' .
        • Filling the blanks with None to facilitate converting to a datetime format in pandas.
      • Remember, line is one row in lines , where each line is enumerated with i . The current line is lines[i] and the next line is lines[i + 1] .
import re

membership_type = list()
member_id = list()
start_date = list()
end_date = list()
name = list()
first_name = list()
middle_name = list()
last_name = list()
with open('test.txt', "r") as f:
    lines = [re.split('\*|/', x.strip().replace('~', '')) for x in f.readlines()] # clean and split each row
    lines = [[i for i in l if i] for l in lines]  # remove blank spaces
    for i, line in enumerate(lines):
        print(line)  # only if you want to see 
        # Member type
        if line[0] == "INS":
            membership_type.append(line[4])
        # Member ID
        elif line[0] == 'REF':
            member_id.append(line[2])
        # Start Dates
        elif (line[0] == 'DTP') and (line[1] == '348'):
            start_date.append(line[3])
            if (lines[i + 1][0] != 'DTP'):  # the next line should be the end_date, if it's not, add None
                end_date.append(None)
        # End Dates
        elif (line[0] == 'DTP') and (line[1] == '349'):
            end_date.append(line[3])
        # Names
        elif line[0] == 'NM1':
            name.append(' '.join(line[3:]))
            first_name.append(line[3])
            middle_name.append(line[4])
            last_name.append(line[5])
            try:
                some_list.append(line[6])
            except IndexError:
                print('No prefix')
                some_list.append(None)

            try:
                some_list.append(line[7])
            except IndexError:
                print('No suffix')
                some_list.append(None)


print(membership_type)
print(member_id)
print(start_date)
print(end_date)
print(name)
print(first_name)
print(middle_name)
print(last_name)

['AL', 'AL']
['690553677', '6905456455']
['20200601', '20200601']
['20200630', None]
['SMITH JOHN PAUL MR JR', 'IMA MEAN TURD MR SR']
['SMITH', 'IMA']
['JOHN', 'MEAN']
['PAUL', 'TURD']

Load into pandas

import pandas as pd

data = {'start_date': start_date , 'end_date': end_date, 'member_id': member_id, 'membership_type': membership_type,
        'name': name, 'first_name': first_name, 'middle_name': middle_name, 'last_name': last_name}

df = pd.DataFrame(data)

# convert datetime columns
df.start_date = pd.to_datetime(df.start_date)
df.end_date = pd.to_datetime(df.end_date)

# display df
  start_date   end_date   member_id membership_type                   name first_name middle_name last_name
0 2020-06-01 2020-06-30   690553677              AL  SMITH JOHN PAUL MR JR      SMITH        JOHN      PAUL
1 2020-06-01        NaT  6905456455              AL    IMA MEAN TURD MR SR        IMA        MEAN      TURD

Contents of test.txt

NM1*IL*1*SMITH*JOHN*PAUL*MR*JR~
INS*Y*18*001*AL*A*E**AC**N~
REF*1L*690553677~
DTP*348*D8*20200601~
DTP*349*D8*20200630~
HD*024**FAC*KJ/165/////1M*IND~
NM1*IL*1*IMA*MEAN*TURD*MR*SR~
INS*Y*18*001*AL*A*E**AC**N~
REF*1L*6905456455~
DTP*348*D8*20200601~
HD*024**FAC*KJ/165/////1M*IND~

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM