def match_couple_hdom(self): ''' Certaines personnes se déclarent en couple avec quelqu'un ne vivant pas au domicile, on les reconstruit ici. Cette étape peut s'assimiler à de la fermeture de l'échantillon. On sélectionne les individus qui se déclarent en couple avec quelqu'un hors du domicile. On match mariés,pacsé d'un côté et sans contrat de l'autre. Dit autrement, si on ne trouve pas de partenaire à une personne mariée ou pacsé on change son statut de couple. Comme pour les liens parents-enfants, on néglige ici la possibilité que le partner soit hors champ (étrange, prison, casernes, etc). Calcul aussi la variable ind['nb_enf'] ''' ind = self.ind couple_hdom = ind['couple'] == 2 # vu leur nombre, on regroupe pacsés et mariés dans le même sac ind.loc[(couple_hdom) & (ind['civilstate'] == 5), 'civilstate'] = 1 # note que du coup, on cherche un partenaire de pacs parmi le sexe opposé. Il y a une petite par technique là dedans qui fait qu'on # ne gère pas les couples homosexuels ## nb d'enfant ind.index = ind['id'] nb_enf_mere = DataFrame(ind.groupby('mere').size(), columns = ['nb_enf']) nb_enf_mere['id'] = nb_enf_mere.index.values nb_enf_pere = DataFrame(ind.groupby('pere').size(), columns = ['nb_enf']) nb_enf_pere['id'] = nb_enf_pere.index # On assemble le nombre d'enfants pour les peres et meres en enlevant les manquantes ( = -1) enf_tot = nb_enf_mere[nb_enf_mere['id'] != -1].append(nb_enf_pere[nb_enf_pere['id'] != -1]).astype(int) ind['nb_enf'] = 0 ind['nb_enf'][enf_tot['id'].values] = enf_tot['nb_enf'] men_contrat = couple_hdom & (ind['civilstate'].isin([1, 5])) & (ind['sexe'] == 0) women_contrat = couple_hdom & (ind['civilstate'].isin([1, 5])) & (ind['sexe'] == 1) men_libre = couple_hdom & (~ind['civilstate'].isin([1, 5])) & (ind['sexe'] == 0) women_libre = couple_hdom & (~ind['civilstate'].isin([1, 5])) & (ind['sexe'] == 1) ind['age'] = ind['agem']//12 var_match = ['age', 'findet', 'nb_enf'] #,'classif', 'dip6' score = "- 0.4893 * other.age + 0.0131 * other.age **2 - 0.0001 * other.age **3 "\ " + 0.0467 * (other.age - age) - 0.0189 * (other.age - age) **2 + 0.0003 * (other.age - age) **3 " \ " + 0.05 * (other.findet - findet) - 0.5 * (other.nb_enf - nb_enf) **2 " match_contrat = Matching(ind.loc[women_contrat, var_match], ind.loc[men_contrat, var_match], score) match_found = match_contrat.evaluate(orderby=None, method='cells') ind.loc[match_found.values,'partner'] = match_found.index ind.loc[match_found.index,'partner'] = match_found.values match_libre = Matching(ind.loc[women_libre, var_match], ind.loc[men_libre, var_match], score) match_found = match_libre.evaluate(orderby=None, method='cells') ind.loc[match_found.values,'partner'] = match_found.index ind.loc[match_found.index,'partner'] = match_found.values # TODO: on pourrait faire un match avec les restants # au lieu de ça, on les considère célibataire ind.loc[men_contrat & (ind['partner'] == -1), ['civilstate', 'couple']] = [2, 3] ind.loc[women_contrat & (ind['partner'] == -1), ['civilstate', 'couple']] = [2, 3] ind.loc[men_libre & ind['partner'] == -1, ['civilstate', 'couple']] = [2, 3] ind.loc[women_libre & ind['partner'] == -1, ['civilstate', 'couple']] = [2, 3] ind.drop(['couple', 'age'], axis = 1, inplace = True) self.ind = ind
def matching_par_enf(self): ''' Matching des parents et des enfants hors du domicile ''' ind = self.ind ind = ind.fillna(-1) ind.index = ind['id'] child_out_of_house = self.child_out_of_house ## info sur les parents hors du domicile des enfants cond_enf_look_par = (ind['per1e'] == 2) | (ind['mer1e'] == 2) enf_look_par = ind[cond_enf_look_par].copy() # Remarque: avant on mettait à zéro les valeurs quand on ne cherche pas le parent, maintenant # on part du principe qu'on fait les choses assez minutieusement enf_look_par['dip6'] = recode(enf_look_par['dip14'], [[30,5], [41,4], [43,3], [50,2], [60,1]] , method='geq') enf_look_par['classif'] = recode(enf_look_par['classif'], [ [[1,2,3],4], [[4,5],2], [[6,7],1], [[8,9], 3], [[10],0]], method='isin') ## nb d'enfant # -- Au sein du domicile nb_enf_mere_dom = ind.groupby('mere').size() nb_enf_pere_dom= ind.groupby('pere').size() # On assemble le nombre d'enfants pour les peres et meres en enlevant les manquantes ( = -1) enf_tot_dom = concat([nb_enf_mere_dom, nb_enf_pere_dom], axis=0) enf_tot_dom = enf_tot_dom.drop([-1]) # -- Hors domicile nb_enf_mere_hdom = child_out_of_house.groupby('mere').size() nb_enf_pere_hdom = child_out_of_house.groupby('pere').size() enf_tot_hdom = concat([nb_enf_mere_hdom, nb_enf_pere_hdom], axis=0) enf_tot_hdom = enf_tot_hdom.drop([-1]) enf_tot = concat([enf_tot_dom, enf_tot_hdom], axis = 1).fillna(0) enf_tot = enf_tot[0] + enf_tot[1] # Sélection des parents ayant des enfants (enf_tot) à qui on veut associer des parents (enf_look_par) enf_tot = (enf_tot.loc[enf_tot.index.isin(enf_look_par.index)].astype(int)).copy() enf_look_par.index = enf_look_par['id'] enf_look_par['nb_enf'] = 0 enf_look_par.loc[enf_tot.index.values, 'nb_enf'] = enf_tot #Note: Attention le score ne peut pas avoir n'importe quelle forme, il faut des espaces devant les mots, à la limite une parenthèse var_match = ['jepnais', 'situa', 'nb_enf', 'anais', 'classif', 'couple', 'dip6', 'jemnais', 'jemprof', 'sexe'] #TODO: gerer les valeurs nulles, pour l'instant c'est très moche #TODO: avoir une bonne distance, on met un gros coeff sur l'age sinon, on a des parents, # plus vieux que leurs enfants score = "- 1000 * (other.anais - anais) **2 - 1.0 * (other.situa - situa) **2 " + \ "- 0.5 * (other.sexe - sexe) **2 - 1.0 * (other.dip6 - dip6) **2 " + \ " - 1.0 * (other.nb_enf - nb_enf) **2" # etape1 : deux parents vivants cond1_enf = (enf_look_par['per1e'] == 2) & (enf_look_par['mer1e'] == 2) cond1_par = (child_out_of_house['pere'] != -1) & (child_out_of_house['mere'] != -1) # TODO: si on fait les modif de variables plus tôt, on peut mettre directement child_out_of_house1 #à cause du append plus haut, on prend en fait ici les premiers de child_out_of_house match1 = Matching(enf_look_par.loc[cond1_enf, var_match], child_out_of_house.loc[cond1_par, var_match], score) parent_found1 = match1.evaluate(orderby=['anais'], method='cells') ind.loc[parent_found1.index.values, ['pere', 'mere']] = child_out_of_house.loc[parent_found1.values, ['pere', 'mere']] #etape 2 : seulement mère vivante enf_look_par.loc[parent_found1.index, ['pere', 'mere']] = child_out_of_house.loc[parent_found1, ['pere', 'mere']] cond2_enf = ((enf_look_par['mere'] == -1)) & (enf_look_par['mer1e'] == 2) cond2_par = ~child_out_of_house.index.isin(parent_found1) & (child_out_of_house['mere'] != -1) match2 = Matching(enf_look_par.loc[cond2_enf, var_match], child_out_of_house.loc[cond2_par, var_match], score) parent_found2 = match2.evaluate(orderby=None, method='cells') ind.loc[parent_found2.index, ['mere']] = child_out_of_house.loc[parent_found2, ['mere']] #étape 3 : seulement père vivant enf_look_par.loc[parent_found2.index, ['pere', 'mere']] = child_out_of_house.loc[parent_found2, ['pere', 'mere']] cond3_enf = ((enf_look_par['pere'] == -1)) & (enf_look_par['per1e'] == 2) cond3_par = ~child_out_of_house.index.isin(parent_found1) & (child_out_of_house['pere'] != -1) # TODO: changer le score pour avoir un lien entre pere et mere plus évident match3 = Matching(enf_look_par.loc[cond3_enf, var_match], child_out_of_house.loc[cond3_par, var_match], score) parent_found3 = match3.evaluate(orderby=None, method='cells') ind.loc[parent_found3.index, ['pere']] = child_out_of_house.loc[parent_found3, ['pere']] print(" au départ on fait " + str(len(parent_found1) + len(parent_found2) + len(parent_found3)) + " match enfant-parent hors dom") # on retire les match non valides to_check = ind[['id', 'agem', 'sexe', 'men', 'partner', 'pere', 'mere', 'lienpref']] tab = to_check.copy() for lien in ['partner', 'pere', 'mere']: tab = tab.merge(to_check, left_on=lien, right_on='id', suffixes=('', '_' + lien), how='left', sort=False) tab.index = tab['id'] for parent in ['pere', 'mere']: diff_age_pere = (tab['agem_' + parent] - tab['agem']) cond = diff_age_pere <= 12*14 print( "on retire " + str(sum(cond)) + " lien enfant " + parent + " car l'âge n'était pas le bon") ind.loc[cond, parent] = -1 cond = (tab['partner'] > -1) & (tab[parent] > -1) & \ (tab[parent] == tab[parent + '_partner']) & \ (tab['men'] != tab['men_' + parent]) print( "on retire " + str(sum(cond)) + " lien enfant " + parent + " car le partner a le même parent") ind.loc[(cond[cond]).index, parent] = -1 self._check_links(ind) self.ind = minimal_dtype(ind) all = self.men.columns.tolist() enfants_hdom = [x for x in all if x[:3]=='hod'] self.drop_variable({'ind':['enf', 'per1e', 'mer1e', 'grandpar'] + ['jepnais', 'jemnais', 'jemprof'], 'men':enfants_hdom})
def matching_par_enf(self): ''' Matching des parents et des enfants hors du domicile ''' ind = self.ind ind = ind.fillna(-1) ind.index = ind['id'] child_out_of_house = self.child_out_of_house ## info sur les parents hors du domicile des enfants cond_enf_look_par = (ind['per1e']==2) | (ind['mer1e']==2) enf_look_par = ind[cond_enf_look_par] # Remarque: avant on mettait à zéro les valeurs quand on ne cherche pas le parent, maintenant # on part du principe qu'on fait les choses assez minutieusement recode(enf_look_par, 'dip14', 'dip6', [[30,5], [41,4], [43,3], [50,2], [60,1]] , method='geq') recode(enf_look_par, 'classif', 'classif2', [ [[1,2,3],4], [[4,5],2], [[6,7],1], [[8,9], 3], [[10],0]], method='isin') enf_look_par.loc[:,'classif'] = enf_look_par.loc[:,'classif2'] ## nb d'enfant # -- Au sein du domicile nb_enf_mere_dom = ind.groupby('mere').size() nb_enf_pere_dom= ind.groupby('pere').size() # On assemble le nombre d'enfants pour les peres et meres en enlevant les manquantes ( = -1) enf_tot_dom = concat([nb_enf_mere_dom, nb_enf_pere_dom], axis=0) enf_tot_dom = enf_tot_dom.drop([-1]) # -- Hors domicile nb_enf_mere_hdom = child_out_of_house.groupby('mere').size() nb_enf_pere_hdom = child_out_of_house.groupby('pere').size() enf_tot_hdom = concat([nb_enf_mere_hdom, nb_enf_pere_hdom], axis=0) enf_tot_hdom = enf_tot_hdom.drop([-1]) enf_tot = concat([enf_tot_dom, enf_tot_hdom], axis = 1).fillna(0) enf_tot = enf_tot[0] + enf_tot[1] # Sélection des parents ayant des enfants (enf_tot) à qui on veut associer des parents (enf_look_par) enf_tot = enf_tot.ix[enf_tot.index.isin(enf_look_par.index)].astype(int) enf_look_par.index = enf_look_par['id'] enf_look_par['nb_enf'] = 0 enf_look_par['nb_enf'][enf_tot.index.values] = enf_tot #Note: Attention le score ne peut pas avoir n'importe quelle forme, il faut des espaces devant les mots, à la limite une parenthèse var_match = ['jepnais','situa','nb_enf','anais','classif','couple','dip6', 'jemnais','jemprof','sexe'] #TODO: gerer les valeurs nulles, pour l'instant c'est très moche #TODO: avoir une bonne distance score = "- 1 * (other.anais - anais) **2 - 1.0 * (other.situa - situa) **2 - 0.5 * (other.sexe - sexe) **2 - 1.0 * (other.dip6 - dip6) \ **2 - 1.0 * (other.nb_enf - nb_enf) **2" # etape1 : deux parents vivants cond1_enf = (enf_look_par['per1e'] == 2) & (enf_look_par['mer1e'] == 2) cond1_par = (child_out_of_house['pere'] != -1) & (child_out_of_house['mere'] != -1) # TODO: si on fait les modif de variables plus tôt, on peut mettre directement child_out_of_house1 #à cause du append plus haut, on prend en fait ici les premiers de child_out_of_house match1 = Matching(enf_look_par.ix[cond1_enf, var_match], child_out_of_house.ix[cond1_par, var_match], score) parent_found = match1.evaluate(orderby=None, method='cells') ind.ix[parent_found.index.values, ['pere','mere']] = child_out_of_house.ix[parent_found.values, ['pere','mere']] #etape 2 : seulement mère vivante enf_look_par.ix[parent_found.index, ['pere','mere']] = child_out_of_house.ix[parent_found, ['pere','mere']] cond2_enf = ((enf_look_par['mere'] == -1)) & (enf_look_par['mer1e'] == 2) cond2_par = ~child_out_of_house.index.isin(parent_found) & (child_out_of_house['mere'] != -1) match2 = Matching(enf_look_par.ix[cond2_enf, var_match], child_out_of_house.ix[cond2_par, var_match], score) parent_found2 = match2.evaluate(orderby=None, method='cells') ind.ix[parent_found2.index, ['mere']] = child_out_of_house.ix[parent_found2, ['mere']] #étape 3 : seulement père vivant enf_look_par.ix[parent_found2.index, ['pere','mere']] = child_out_of_house.ix[parent_found2, ['pere','mere']] cond3_enf = ((enf_look_par['pere'] == -1)) & (enf_look_par['per1e'] == 2) cond3_par = ~child_out_of_house.index.isin(parent_found) & (child_out_of_house['pere'] != -1) # TODO: changer le score pour avoir un lien entre pere et mere plus évident match3 = Matching(enf_look_par.ix[cond3_enf, var_match], child_out_of_house.ix[cond3_par, var_match], score) parent_found3 = match3.evaluate(orderby=None, method='cells') ind.ix[parent_found3.index, ['pere']] = child_out_of_house.ix[parent_found3, ['pere']] self.ind = minimal_dtype(ind) all = self.men.columns.tolist() enfants_hdom = [x for x in all if x[:3]=='hod'] self.drop_variable({'ind':['enf','per1e','mer1e','grandpar'] + ['jepnais','jemnais','jemprof'], 'men':enfants_hdom})