2017-09-12 2 views
0

EDIT: je réalise que je mis mon exemple de manière incorrecte, la version corrigée suit:Python: itérer sur dataframes de différentes longueurs, et calculer une nouvelle valeur avec des valeurs répétées

J'ai deux dataframes:

df1 = pd.DataFrame({'x values': [11, 12, 13], 'time':[1,2.2,3.5}) 
df2 = pd.DataFrame({'x values': [11, 21, 12, 43], 'time':[1,2.1,2.6,3.1}) 

Ce que je dois faire est itérer sur ces deux dataframes, et calculer une nouvelle valeur, qui est un ratio des valeurs de x dans df1 et df2. La difficulté vient parce que ces données sont de différentes longueurs.

Si je voulais juste calculer des valeurs dans les deux, je sais que je pourrais utiliser quelque chose comme zip, ou même carte. Malheureusement, je ne veux pas laisser tomber de valeurs. Au lieu de cela, je dois être capable de comparer la colonne de temps entre les deux cadres pour déterminer si oui ou non pour copier sur une valeur d'un temps antérieur au calcul de dans la période de temps suivante.

Ainsi, par exemple, je calculerait le premier rapport:

df1["x values"][0]/df2["x values"][0] 

Alors, pour la seconde, je vérifie que la mise à jour qui se passera ensuite, qui dans ce cas est de DF2, donc DF1 [ « temps »] < DF2 [ "temps"] et:

df1["x values"][0]/df2["x values"][1] 

Pour la troisième, je voyais que DF1 [ "temps"]> DF2 [ "temps"], de sorte que le troisième calcul serait:

df1["x values"][1]/df2["x values"][1] 

La seule fois où les deux valeurs doivent être utilisées pour calculer le rapport à partir de la même "position" est si les temps dans les deux données sont égaux.

Et ainsi de suite. Je suis très confus quant à savoir si c'est possible d'exécuter en utilisant quelque chose comme une fonction lambda, ou itertools. J'ai fait quelques tentatives, mais la plupart ont donné des erreurs. Toute aide serait appréciée.

Répondre

0

Voici ce que je fini par faire. J'espère que cela aidera à clarifier ma question. En outre, si quelqu'un peut penser à une façon plus pythonique de le faire, j'apprécierais les commentaires.

#add a column indicating which 'type' of dataframe it is 
df1['type']=pd.Series('type1',index=df1.index) 
df2['type']=pd.Series('type2',index=df2.index) 

#concatenate the dataframes 
df = pd.concat((df1, df2),axis=0, ignore_index=True) 

#sort by time 
df = df.sort_values(by='time').reset_index() 

#we create empty arrays in order to track records 
#in a way that will let us compute ratios 
x1 = [] 
x2 = [] 

#we will iterate through the dataframe line by line 
for i in range(0,len(df)): 

    #if the row contains data from df1 
    if df["type"][i] == "type1": 

     #we append the x value for that type 
     x1.append(df[df["type"]=="type1"]["x values"][i]) 

     #if the x2 array contains exactly 1 value 
     if len(x2) == 1: 
       #we add it to match the number of x1 
       #that we have recorded up to that point 
       #this is useful if one time starts before the other 
       for j in range(1, len(x1)-1): 
        x2.append(x2[0]) 

     #if the x2 array contains more than 1 value 
     #add a copy of the previous x2 record to correspond 
     #to the new x1 record 
     if len(x2) > 0: 
       x2.append(x2[len(x2)-1]) 

    #if the row contains data from df2 

    if df["type"][i] == "type2": 

     #we append the x value for that type 
     x2.append(df[df["type"]=="type2"]["x values"][i]) 

     #if the x1 array contains exactly 1 value 
     if len(x1) == 1: 
       #we add it to match the number of x2 
       #that we have recorded up to that point 
       #this is useful if one time starts before the other 
       for j in range(1, len(x2)-1): 
        x1.append(x2[0]) 

     #if the x1 array contains more than 1 value 
     #add a copy of the previous x1 record to correspond 
     #to the new x2 record 
     if len(x1) > 0: 
       x1.append(x1[len(x1)-1]) 

#combine the records 
new__df = pd.DataFrame({'Type 1':x1, 'Type 2': x2}) 
#compute the ratio 
new_df['Ratio'] = new_df['x1']/f_df['x2'] 
0

Vous pouvez fusionner les deux dataframes sur le temps et le calcul des ratios

new_df = df1.merge(df2, on = 'time', how = 'outer') 
new_df['ratio'] = new_df['x values_x']/new_df['x values_y'] 

Vous obtenez

time x values_x x values_y ratio 
0 1  11   11   1.000000 
1 2  12   21   0.571429 
2 2  12   12   1.000000 
3 3  13   43   0.302326 
+0

Le problème est que j'ai simplifié mon exemple, si le temps ne correspond pas réellement entre les deux cadres - ils ont des dates différentes – Sveinn

+0

Oh alors quelle serait la base de trouver le rapport? – Vaishali

+0

J'ai essentiellement besoin d'obtenir des ratios pour toutes les valeurs "mises à jour". Donc, si vous pensez que le temps est linéaire, chaque fois que j'ai une valeur x associée à une nouvelle période, j'ai besoin de mettre à jour le calcul du ratio. Je suis donc en train de suivre l'évolution du ratio au fil du temps. Je me rends compte maintenant que j'ai mis en place mon exemple un peu incorrectement. – Sveinn