<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Grouping all encounter nbrs under respective person nbr
Step1:  Now grouping other measurements and properties under encounter_nbrs
Step2:  Aggregating encounter entities under respective person entity
Step3:  Dropping duplicated columns and then full na rows across tables
<ASSISTANT_TASK:>
Python Code:
encounter_key = 'Enc_Nbr'
person_key = 'Person_Nbr'
encounters_by_person = {}
for df in dfs:
    if df is not None:
        df_columns =set(df.columns.values)
        if encounter_key in df_columns and person_key in df_columns:
            for row_index, dfrow in df.iterrows():
                rowdict = dict(dfrow)
                person_nbr = rowdict[person_key]
                encounter_nbr = rowdict[encounter_key]
                encounters_by_person.setdefault(person_nbr, set()).add(encounter_nbr)
for person_nbr in encounters_by_person:
    if len(encounters_by_person[person_nbr])>5:
        pprint(encounters_by_person[person_nbr])
        break
Explanation: Grouping all encounter nbrs under respective person nbr
End of explanation
encounter_key = 'Enc_Nbr'
# columns_to_ignore = [u'Person_ID', u'Person_Nbr', u'Enc_ID', u'Enc_Nbr', u'Enc_Date']
data_by_encounters = {}
data_by_encounters_type = {}
for df_index, df in enumerate(dfs):
    df_name = table_names[df_index]
    print df_name
    data_by_encounters[df_name] = {}
    if df is not None:
        df_columns =set(df.columns.values)
        if encounter_key in df_columns:
            # check if encounter is primary key in the table
            if len(df) == len(df[encounter_key].unique()):
                data_by_encounters_type[df_name] = 'single'
                for row_index, dfrow in df.iterrows():
                    rowdict = dict(dfrow)
                    
                    for k, v in rowdict.iteritems():
                        if isinstance(v, pd.tslib.Timestamp):
                            rowdict[k] = v.toordinal()
                    
                    encounter_nbr = rowdict[encounter_key]
                    data_by_encounters[df_name][encounter_nbr] = rowdict
            else:
                data_by_encounters_type[df_name] = 'list'
                for row_index, dfrow in df.iterrows():
                    rowdict = dict(dfrow)
                    for k, v in rowdict.iteritems():
                        if isinstance(v, pd.tslib.Timestamp):
                            rowdict[k] = v.toordinal()
                    encounter_nbr = rowdict[encounter_key]
                    data_by_encounters[df_name].setdefault(encounter_nbr, []).append(rowdict)
Explanation: Now grouping other measurements and properties under encounter_nbrs
End of explanation
all_persons = []
for person_nbr in encounters_by_person:
    person_object = {person_key:person_nbr, 'encounter_objects':[]}
    for enc_nbr in encounters_by_person[person_nbr]:
        encounter_object = {encounter_key: enc_nbr}
        for df_name in data_by_encounters_type:
            if enc_nbr in data_by_encounters[df_name]:
                encounter_object[df_name] = data_by_encounters[df_name][enc_nbr]
                if data_by_encounters_type[df_name] !="single":
                    encounter_object[df_name+"_count"] = len(data_by_encounters[df_name][enc_nbr])
        person_object['encounter_objects'].append(encounter_object)
    all_persons.append(person_object)
# checking for aggregation consistency
n = 0
for person in all_persons:
    person_nbr=person[person_key]
    for enc_obj in person['encounter_objects']:
        enc_nbr=enc_obj[encounter_key]
        for df_name in data_by_encounters_type:
            if data_by_encounters_type[df_name] == "single":
                if df_name in enc_obj:
                    if person_key in enc_obj[df_name]:
                        if person_nbr != enc_obj[df_name][person_key]:
                            print "Person nbr does not match", person_nbr, enc_nbr, df_name
                    if encounter_key in enc_obj[df_name]:
                        if enc_nbr != enc_obj[df_name][encounter_key]:
                            print "Encounter nbr does not match", person_nbr, enc_nbr, df_name
                
            else:
                if df_name in enc_obj:
                    for rp_index, repeated_property in enumerate(enc_obj[df_name]):
                        if person_key in repeated_property:
                            if person_nbr != repeated_property[person_key]:
                                print "Person nbr does not match", person_nbr, enc_nbr, df_name, rp_index
                        if encounter_key in repeated_property:
                            if enc_nbr != repeated_property[encounter_key]:
                                print "Encounter nbr does not match", person_nbr, enc_nbr, df_name, rp_index
            
            
#     n+=1
#     if n>2:break
Explanation: Aggregating encounter entities under respective person entity
End of explanation
with open('20170224_encounter_objects_before_duplicate_fields_drop.json', 'w') as fh:
    json.dump(all_persons, fh)
# drop repeated columns in nested fields except from table "encounters"
columns_to_drop = ['Enc_ID', 'Enc_Nbr', 'Enc_Date', 'Person_ID', 'Person_Nbr','Date_Created', 'Enc_Timestamp']
for person_index in range(len(all_persons)):
    
    for enc_obj_index in range(len(all_persons[person_index]['encounter_objects'])):
    
        enc_obj = all_persons[person_index]['encounter_objects'][enc_obj_index]
    
        for df_name in data_by_encounters_type:
            if data_by_encounters_type[df_name] == "single":
                if df_name in enc_obj and df_name!='encounters':
                    for column_to_drop in columns_to_drop:
                        try:
                            del enc_obj[df_name][column_to_drop]
                        except:
                            pass
                
            else:
                if df_name in enc_obj and df_name!='encounters':
                    for rp_index in range(len(enc_obj[df_name])):
                        for column_to_drop in columns_to_drop:
                            try:
                                del enc_obj[df_name][rp_index][column_to_drop]
                            except:
                                pass
                    
            
        all_persons[person_index]['encounter_objects'][enc_obj_index] = enc_obj
# drop full na object rows
# !does not seem to be working!!
for person_index in range(len(all_persons)):
    
    for enc_obj_index in range(len(all_persons[person_index]['encounter_objects'])):
        enc_obj = all_persons[person_index]['encounter_objects'][enc_obj_index]
        for df_name in data_by_encounters_type:
            if data_by_encounters_type[df_name] == "single":
                if df_name in enc_obj:
                    if all(pd.isnull(enc_obj[df_name].values())):
                        enc_obj[df_name] = float('nan')
            else:
                if df_name in enc_obj:
                    for rp_index in reversed(range(len(enc_obj[df_name]))):
                        if all(pd.isnull(enc_obj[df_name][rp_index].values())):
                            del enc_obj[df_name][rp_index]
        
        all_persons[person_index]['encounter_objects'][enc_obj_index] = enc_obj
with open('20170224_encounter_objects.json', 'w') as fh:
    json.dump(all_persons, fh)
# creating a dataframe from aggregated data
combined_ecounters_df = pd.DataFrame.from_dict({(person_obj[person_key],enc_obj[encounter_key]): enc_obj
                           for person_obj in all_persons
                           for enc_obj in person_obj['encounter_objects']},
                       orient='index')
combined_ecounters_df.head(10)
combined_ecounters_df.loc[89,'family_hist_for_Enc']
Explanation: Dropping duplicated columns and then full na rows across tables
End of explanation
<END_TASK>