Python Forum

Full Version: Help Fix My Function
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hi All,

I am new to python and have a number of csv files and am trying to get the count of people who have died and suffered a fall or died and not suffered a fall. I also am trying to work out the average age people lived with each of the above conditions but am having issues tweaking a function. The function in the code below is def is65, I have underlined the relevant aspects below. The function currently subtracts DOB from current date to work out the age, what I am trying to do is to subtract the DOB from the DOD instead. The DOD is from a csv file named DEATHREG (I have also bolded and underlined), problem is no matter how I try to reference the DOD in def is65 it does not work. Any help will be welcome
import csv
from datetime import datetime

def get_years(delta_in):
    """Get years from timedelta"""
    return delta_in.days / 365.25

class PersonData(object):
    def __init__(self, dem_data):
        """Initialize person data with dictionary of demographic data from GP_DEM.csv
        :param dem_data: dict
        """
        self.data = dict()
        # clinical events
        self.clin = []
        # hospital events
        self.hosp = []
        self.list_names = {'GP_CLIN': self.clin, 'HOSPDAT': self.hosp}
        # initialize data with dictionary provided
        self.add_data(dem_data)
        # first fall event will be written here
        self.first_fall_event = None
    def is65(self):
        """Return True if the person is older than 65 years"""
        return get_years(cur_datetime - all_persons[patid].data['DOB']) > 65
    def get_first_fall_event_date(self):
        """Get datetime of the first fall event if exists"""
        if self.first_fall_event:
            return self.first_fall_event
        fall_events = []
        # iterate through all events
        for hosp_event in self.hosp:
            # check for event code
            event_code = hosp_event['EVENT_CODE']
            if event_code[:3] in fall_event_codes:
                # if fall event, append to the temporary list of fall events
                fall_events.append(hosp_event['EVENT_DATE'])
        if fall_events:  # if found:
            # first date of fall events
            first_event = sorted(fall_events)[0]
            self.first_fall_event = first_event
            return first_event
        # if not found:
        return False
    def add_data(self, data_dict, keys_to_add=None, list_name=''):
        """Add data to this object's dataset"""
        # check for necessary keys to add
        if keys_to_add:
            new_data = {key: value for key, value in data_dict.items() if key in keys_to_add}
        else:
            new_data = data_dict
        # converting date to datetime format
        for date_code in ['EVENT_DATE', 'DOB', 'DOD']:
            if date_code in new_data:
                new_data[date_code] = datetime.strptime(new_data[date_code], '%Y-%m-%d %H:%M:%S')
        # if data should go to the list:
        if list_name:
            if list_name in self.list_names:
                self.list_names[list_name].append(new_data)
        # if data goings to the dictionary
        else:
            self.data.update(new_data)

def add_data_from_csv(file_name, keys_to_add=None, list_name=''):
    """Add data from certain csv file to all_persons dictionary
    :param file_name: str
    :param keys_to_add: list
    :param list_name: str
    """
    global all_persons
    with open(file_name) as input_file:
        input_csv = csv.DictReader(input_file, delimiter=',')
        # iterating through all lines in csv file
        for line in input_csv:
            patid = get_patid(line['PATID'])
            if patid in all_persons:
                all_persons[patid].add_data(line, keys_to_add=keys_to_add, list_name=list_name)
            else:
                # if PATID not found, do nothing
                pass

with open('GP_DEM.csv') as input_file:
    input_csv = csv.DictReader(input_file, delimiter=',')
    # all persons data dictionary {PATID1: PersonData1, ...}
    all_persons = {line['PATID']: PersonData(line) for line in input_csv}

add_data_from_csv('DEATHREG.csv', ['DOD', 'CAUSE'])
add_data_from_csv('GP_CLIN.csv', ['GPID', 'EVENT_DATE', 'EVENT_CODE', 'EVENT_DATA'], list_name='GP_CLIN')
add_data_from_csv('HOSPDAT.csv', ['HOSPID', 'EVENT_DATE', 'EVENT_CODE'], list_name='HOSPDAT')

# {PATID: [years before first fall event, years after the first}
patid_years = dict()
for patid in all_persons:
    person = all_persons[patid]
    # use only persons with ages > 65 years
    if not person.is65():
        continue
    # get first fall event date-time
    first_event = person.get_first_fall_event_date()
    # if no fall events, use other persons
    if not first_event:
        continue
    # if person died
    if 'DOD' in person.data:
        years_after = get_years(person.data['DOD'] - first_event)
    else:  # if not died, use current date
        years_after = get_years(cur_datetime - first_event)
    # get years before the first fall event
    years_before = get_years(first_event - person.data['DOB'])
    # {PATID: [years before first fall event, years after the first}
    patid_years[patid] = [years_before, years_after]
print('2)a) Counting how many persons:')
no_falls = 0
with_falls = 0
# iterate through all persons
for patid in all_persons:
    person = all_persons[patid]
    # check if person is 65 years old, if died, and without fall events
    if person.is65() and ('DOD' in person.data):
        if not person.get_first_fall_event_date():
            no_falls += 1
        else:
            with_falls += 1
print('i. The person is over the age of 65 years old, has died and DID NOT suffer a fall event:')
print(no_falls)
print('ii. The person is over the age of 65 years old, has died and HAS suffer at least one fall event in their life:')
print(with_falls)
(Nov-23-2016, 07:25 PM)PietonNewbie Wrote: [ -> ]problem is no matter how I try to reference the DOD in def is65 it does not work
Can you reproduce your problem with <20 lines of code, an example (short) CSV file, zero globals, and more detail on what the expected vs. actual results are beyond "it does not work"?
Why are you referencing all_persons[patid].data['DOB']? Why not reference self.data['DOB']?