1
votes

Division de 2 lignes dans une colonne correspondant à deux autres colonnes et leur relation (Python)

J'ai une dataframe ci-dessous, ce que je veux, c'est que chaque élément de la colonne "nom_1" effectue une division de sa cible_1 correspondante à target_0. Ainsi, pour "Circle" , le "id" pour "target_1" est 9168 et "id" pour "target_0" est 28152. J'ai besoin de la division de 9168/28152. Je pourrais le faire manuellement mais j'ai besoin qu'il soit automatisé car il y aura beaucoup plus de dataframes que celui-ci avec des valeurs uniques différentes.

J'ai besoin de créer un dictionnaire qui ressemble à ceci:

    nom_1  target     id
0      Circle       0  28152
1      Circle       1   9168
2     Polygon       0  24741
3     Polygon       1  11402
4      Square       0  32787
5      Square       1  16810
6        Star       0  31645
7        Star       1  14259
8   Trapezoid       0  71833
9   Trapezoid       1  29348
10   Triangle       0  19078
11   Triangle       1  10777

nom_1_dat = train.groupby(["nom_1","target"]).count()[["id"]].reset_index()

print(nom_1_dat)

nom_1_dict = {}
i_list = []
for i,element in enumerate(nom_1_dat["nom_1"]):
    i_list.append(i)
for i,element in enumerate(nom_1_dat["nom_1"]):
    if (i+1) < max(i_list): 
        nom_1_dict[element] = (nom_1_dat["id"][i+1])/(nom_1_dat["id"][i])

print(nom_1_dict)

Remarque : ces chiffres ne représentent pas simplement le résultat réel le format que je voudrais

Voici mon code pour l'instant:

{'Circle': 0.3705589911482963, 'Polygon': 0.34775978284076003, 'Square': 0.5312055617001106, 'Star': 0.19850208121615415, 'Trapezoid': 1.5383163853653423} 


0 commentaires

3 Réponses :


1
votes

Essayez ceci:

dict={}
values = df['nom_1'].unique() # find the norm_1 unique_values
for value in values:       # iterate over values
    df_t=df[df['nom_1']==value] # get the value from dataframe
    dict[value]=int(df_t[df_t['target']==1]['id'])/int(df_t[df_t['target']==0]['id'])  # divide the target_1/target_0
print(dict)

J'espère que cela vous aidera!


0 commentaires

4
votes

Étant donné le dataframe suivant:

dict_res = df_res.to_dict()['id']
# output: {'Circle': 0.3256606990622336, 'Polygon': 0.46085445212400467}

Essayez ce code, en utilisant groupby.agg :

               id
nom_1            
Circle   0.325661
Polygon  0.460854

ou équivalent, en utilisant groupby.apply : p >

df_res = df.groupby('nom_1').apply(lambda row: (row[row.target==1]['id'].iloc[0]/row[row.target==0]['id'].iloc[0]))

Dans les deux cas, donne:

df_res = df.groupby('nom_1').agg({'id': lambda row_id: row_id[1]/row_id[0]})

Si vous voulez convertir le résultat en dictionnaire:

df=pd.DataFrame([['Circle', 'Circle', 'Polygon', 'Polygon'], [0, 1, 0, 1], [28152, 9168, 24741, 11402]], ['nom_1', 'target', 'id']).T
     nom_1 target     id
0   Circle      0  28152
1   Circle      1   9168
2  Polygon      0  24741
3  Polygon      1  11402


4 commentaires

J'obtiens une KeyError avec le premier code. Je ne sais pas si je peux publier du code dans les commentaires, mais laissez-moi essayer. df = train.groupby (["nom_1", ​​"cible"]). count () [["id"]]. reset_index () print (df) nom_1_m = df.groupby ('nom_1'). agg ({' id ': lambda row_id: row_id [1] / row_id [0]}) dict_res = nom_1_m.to_dict () [' id ']


L'erreur dans votre code se trouve sur la première ligne lorsque vous créez df , mais je ne peux pas vous aider car je ne connais pas le format de vos données train . Les lignes de code suivantes que j'ai publiées sont correctes. Essayez de mettre à jour votre question et d'ajouter des valeurs de train. Cependant, si vous essayez la saisie de ma réponse, vous obtenez le résultat que vous recherchiez


Oui, @Massifox j'ai ajouté ma solution comme réponse. Votre solution version n ° 2 fonctionnait pour les colonnes à faible cardinalité mais j'ai obtenu une KeyError pour celles à cardinalité élevée avec plus de 2000 valeurs uniques. Je ne sais pas vraiment si cela est dû à une cardinalité élevée, j'ai essayé de déboguer pour voir le problème derrière l'erreur, mais je n'ai pas pu le comprendre. Merci beaucoup de m'avoir aidé !


Je ne pense pas que ce soit un problème de cardinalité, vous avez probablement une valeur manquante / sale dans le jeu de données du train, ce qui à un moment donné vous fait accéder à un champ qui n'existe pas / nul en générant 'KeyError'. Sans voir le jeu de données, je ne peux pas vous aider :-) L'important est que vous ayez réussi à résoudre! Si vous pensez que ma réponse vous a peut-être aidé, acceptez-la et votez pour elle! Merci



0
votes

J'ai essayé les réponses données. Quand je les ai essayés sur des colonnes avec une cardinalité élevée, j'ai obtenu une KeyError. J'ai modifié mon code précédent et j'ai obtenu le résultat souhaité:

#output:
{'Circle': 0.3256606990622336, 'Polygon': 0.46085445212400467, 'Square': 
0.5127032055387806, 'Star': 0.45059251066519196, 'Trapezoid': 0.40855874041178847, 
'Triangle': 0.5648914980605934}

nom_1_dat = train.groupby(["nom_1","target"]).count()[["id"]].reset_index()
print(nom_1_dat)
nom_1_dict = {}
i_list = []
for i,element in enumerate(nom_1_dat["nom_1"]):
    i_list.append(i)
for i,element in enumerate(nom_1_dat["nom_1"]):
    if element not in nom_1_dict.keys():
        nom_1_dict[element] = (nom_1_dat["id"][i+1])/(nom_1_dat["id"][i])
print(nom_1_dict)


0 commentaires