web-dev-qa-db-fra.com

iterrows pandas obtenir la valeur des lignes suivantes

J'ai un df dans les pandas

import pandas as pd
df = pd.DataFrame(['AA', 'BB', 'CC'], columns = ['value'])

Je veux parcourir les lignes en df. Pour chaque ligne, je veux rows value and next rows value Quelque chose comme (ça ne marche pas):

for i, row in df.iterrows():
     print row['value']
     i1, row1 = next(df.iterrows())
     print row1['value']

En conséquence, je veux

'AA'
'BB'
'BB'
'CC'
'CC'
*Wrong index error here  

À ce stade, j'ai un moyen de résoudre ce problème

for i in range(0, df.shape[0])
   print df.irow(i)['value']
   print df.irow(i+1)['value']

Existe-t-il un moyen plus efficace de résoudre ce problème?

27
Ayrat

Premièrement, votre "façon désordonnée" est correcte, il n'y a rien de mal à utiliser des indices dans la trame de données, et ce ne sera pas trop lent. iterrows () lui-même n'est pas terriblement rapide.

Une version de votre première idée qui fonctionnerait serait:

row_iterator = df.iterrows()
_, last = row_iterator.next()  # take first item from row_iterator
for i, row in row_iterator:
    print(row['value'])
    print(last['value'])
    last = row

La deuxième méthode pourrait faire quelque chose de similaire, pour enregistrer un index dans la trame de données:

last = df.irow(0)
for i in range(1, df.shape[0]):
    print(last)
    print(df.irow(i))
    last = df.irow(i)

Lorsque la vitesse est critique, vous pouvez toujours essayer les deux et chronométrer le code.

19
alisdt

Il existe un exemple de fonction pairwise() dans le document itertools:

from itertools import tee, izip
def pairwise(iterable):
    "s -> (s0,s1), (s1,s2), (s2, s3), ..."
    a, b = tee(iterable)
    next(b, None)
    return izip(a, b)

import pandas as pd
df = pd.DataFrame(['AA', 'BB', 'CC'], columns = ['value'])

for (i1, row1), (i2, row2) in pairwise(df.iterrows()):
    print i1, i2, row1["value"], row2["value"]

Voici la sortie:

0 1 AA BB
1 2 BB CC

Mais, je pense que les lignes iter dans un DataFrame sont lentes, si vous pouvez expliquer quel est le problème que vous voulez résoudre, je peux peut-être suggérer une meilleure méthode.

10
HYRY

J'utiliserais la fonction shift () comme suit:

df['value_1'] = df.value.shift(-1)
[print(x) for x in df.T.unstack().dropna(how = 'any').values];

qui produit

AA
BB
BB
CC
CC

Voici comment fonctionne le code ci-dessus:

Étape 1) Utilisez la fonction shift

df['value_1'] = df.value.shift(-1)
print(df)

produit

value value_1
0    AA      BB
1    BB      CC
2    CC     NaN

étape 2) Transposer:

df = df.T
print(df)

produit:

          0   1    2
value    AA  BB   CC
value_1  BB  CC  NaN

Étape 3) Désempiler:

df = df.unstack()
print(df)

produit:

0  value       AA
   value_1     BB
1  value       BB
   value_1     CC
2  value       CC
   value_1    NaN
dtype: object

Étape 4) Supprimez les valeurs NaN

df = df.dropna(how = 'any')
print(df)

produit:

0  value      AA
   value_1    BB
1  value      BB
   value_1    CC
2  value      CC
dtype: object

Étape 5) Renvoyez une représentation Numpy du DataFrame et imprimez valeur par valeur:

df = df.values
[print(x) for x in df];

produit:

AA
BB
BB
CC
CC
3
Anna K.

Cela peut aussi être résolu en izipping le dataframe (itérateur) avec une version offset de lui-même.

Bien sûr, l'erreur d'indexation ne peut pas être reproduite de cette façon.

Regarde ça

import pandas as pd
from itertools import izip

df = pd.DataFrame(['AA', 'BB', 'CC'], columns = ['value'])   

for id1, id2 in izip(df.iterrows(),df.ix[1:].iterrows()):
    print id1[1]['value']
    print id2[1]['value']

qui donne

AA
BB
BB
CC
2
Acorbe

une combinaison de réponses m'a donné un temps d'exécution très rapide. en utilisant la méthode shift pour créer une nouvelle colonne des valeurs de ligne suivantes, puis en utilisant la fonction row_iterator comme @alisdt l'a fait, mais ici je l'ai changé de iterrows = to itertuples qui est 100 fois plus rapide.

mon script est pour itérer la trame de données des duplications de longueur différente et ajouter une seconde pour chaque duplication afin qu'elles soient toutes uniques.

# create new column with shifted values from the departure time column
df['next_column_value'] = df['column_value'].shift(1)
# create row iterator that can 'save' the next row without running for loop
row_iterator = df.itertuples()
# jump to the next row using the row iterator
last = next(row_iterator)
# because pandas does not support items alteration i need to save it as an object
t = last[your_column_num]
# run and update the time duplications with one more second each
for row in row_iterator:
    if row.column_value == row.next_column_value:
         t = t + add_sec
         df_result.at[row.Index, 'column_name'] = t
    else:
         # here i resetting the 'last' and 't' values
         last = row
         t = last[your_column_num]

J'espère que cela vous aidera.

0
R.V