Am un DataFrame` la panda:
import pandas as pd
inp = [{'c1':10, 'c2':100}, {'c1':11,'c2':110}, {'c1':12,'c2':120}]
df = pd.DataFrame(inp)
print df
Ieșire:
c1 c2
0 10 100
1 11 110
2 12 120
Acum vreau să itera peste rândurile de acest cadru. Pentru fiecare rând vreau să fie în măsură pentru a accesa elementele sale (valori în celule) cu numele de coloane. De exemplu:
for row in df.rows:
print row['c1'], row['c2']
Este posibil să faci asta la panda?
Am găsit asta întrebare similară. Dar nu mi-a dat răspunsul de care am nevoie. De exemplu, se recomandă să nu pentru a utiliza:
for date, row in df.T.iteritems():
sau
for row in df.iterrows():
Dar eu nu înțeleg de ce " row " obiect este și cum pot lucra cu ea.
DataFrame.iterrows este un generator care produc atât indicele de rând și
import pandas as pd
import numpy as np
df = pd.DataFrame([{'c1':10, 'c2':100}, {'c1':11,'c2':110}, {'c1':12,'c2':120}])
<!- ->
for index, row in df.iterrows():
print(row['c1'], row['c2'])
Output:
10 100
11 110
12 120
Ia în considerare mai întâi dacă aveți cu adevărat nevoie de a repeta peste rânduri într-un DataFrame. A se vedea acest răspuns de alternative.
Dacă aveți în continuare nevoie pentru a itera peste rânduri, puteți utiliza metodele de mai jos. Notă unele avertismente importante care nu sunt menționate în oricare dintre celelalte răspunsuri.
pentru index, rând din df.iterrows(): imprimare rând["c1"], rând["c2"]
de rând în df.itertuples(index=True, name='Panda'): imprimare getattr(rd, "c1"), getattr(rd, "c2")
itertuples()
ar trebui să fie mai rapid decât iterrows()
Dar să fie conștienți, potrivit docs (panda 0.24.2 la acest moment):
dtype
s-ar putea să nu se potrivească la rând la rândPentru că iterrows returnează o Serie pentru fiecare rând, se nu păstra dtypes peste rânduri (dtypes sunt conservate peste coloane pentru DataFrames). Pentru a păstra dtypes în timp ce iterarea peste rânduri, este mai bine să utilizați itertuples() care returnează namedtuples de valori și care este, în general, mult mai repede decât iterrows()
Tu ar trebui să nu modificați niciodată ceva ce sunt iterarea peste. Acest lucru nu este garantat de a lucra în toate cazurile. În funcție de tipuri de date, iterator returnează o copie și nu un punct de vedere, și a scris pentru a nu va avea niciun efect.
Utilizarea DataFrame.apply() în loc:
new_df = df.aplica(lambda x: x * 2)
numele coloanelor va fi redenumită în poziție de nume dacă acestea sunt incorecte Python identificatori, repetate, sau de a începe cu un caracter de subliniere. Cu un număr mare de coloane (>255), regulat tupluri sunt returnate.
A se vedea panda docs pe repetare pentru mai multe detalii.
Cum să itera peste rânduri într-un DataFrame la Panda?
Răspuns: DON'T!
Repetare în panda este un anti-model, și este ceva ce ar trebui să vrei să faci doar atunci cand ai epuizat toate celelalte opțiuni posibile. Tu nu ar trebui să ia în considerare folosind orice funcție, cu " iter" în numele său pentru ceva mai mult decât câteva mii de rânduri sau va trebui să te obișnuiești cu un mult de așteptare. Vrei pentru a imprima un DataFrame? Utilizarea
DataFrame.to_string()
. Vrei pentru a calcula ceva? În acest caz, de căutare pentru metodele în această ordine (lista modificat de aici):
- Vectorizare
- Cython rutine
- List Comprehensions (vanilie "pentru" bucla)
DataFrame.apply()
: i) Reduceri care pot fi efectuate în cython, ii) Repetare în python spațiuDataFrame.itertuples()
șiiteritems()
DataFrame.iterrows()
iterrows " și " itertuples
(ambele primit mai multe voturi în răspunsurile la această întrebare) ar trebui să fie utilizate în cazuri foarte rare, cum ar fi generarea de rând obiecte/nametuples pentru procesarea secvențială, care este de fapt singurul lucru pe care aceste funcții sunt utile pentru. Apel la Autoritate Docs page pe iterație are o mare roșie de avertizare cutie pe care scrie: Iterarea prin panda obiecte este în general lent. În multe cazuri, iterarea manual pe rânduri nu este necesară [...].Mai repede decât în Buclă: Vectorizare, Cython
Un mare număr de operații de bază și calcule sunt "vectorised" de panda (fie prin NumPy, sau prin Cythonized funcții). Aceasta include aritmetica, comparații, (cele mai multe) reduceri, remodelarea (cum ar fi de pivotare), se alătură, și groupby operațiuni. Uită-te prin documentația pe Esențiale de Bază Functionality pentru a găsi un adecvat vectorised metodă pentru problema ta. Dacă nu există nici una, nu ezitați să scrie propriul dvs. folosind comanda cython extensions.
Următorul Lucru: List Comprehensions
List comprehensions ar trebui să fie următorul port de escală dacă 1) nu există nici vectorized soluție disponibilă, 2) de performanță este important, dar nu suficient de important pentru a merge prin hassle de cythonizing codul, și 3) ai're încercarea de a efectua elementwise transformare pe cod. Nu este o sumă bună de probă](https://stackoverflow.com/questions/54028199/for-loops-with-pandas-when-should-i-care) să sugereze că list comprehensions sunt suficient de repede (și uneori chiar mai repede) pentru multe comune panda sarcini. Formula este simpla,
# iterating over one column - `f` is some function that processes your data
result = [f(x) for x in df['col']]
# iterating over two columns, use `zip`
result = [f(x, y) for x, y in zip(df['col1'], df['col2'])]
# iterating over multiple columns
result = [f(row[0], ..., row[n]) for row in df[['col1', ...,'coln']].values]
Las's a demonstra diferența cu un exemplu simplu de a adăuga doi ursi panda coloane A + B
. Aceasta este o vectorizable misiune, astfel încât acesta va fi ușor pentru a compara performanța metodelor discutate mai sus.
Benchmarking cod, pentru referință.
Trebuie să menționez, totuși, că nu este't întotdeauna atât de tăiat și uscat. Uneori răspunsul la "ce este cea mai bună metodă pentru o operație" este "aceasta depinde de dvs. de date". Sfatul meu este de a testa diferite abordări cu privire la datele dumneavoastră înainte de a ajunge la unul.
iter*
de familie. Există, totuși, situații în care se poate (sau ar trebui) să ia în considerare "se aplică" și o serie alternativă, mai ales în unele `GroupBy de operațiuni).
* Panda șir de metode sunt "vectorized", în sensul că acestea sunt specificate pe serie, dar funcționează pe fiecare element. Mecanismele care stau la baza sunt încă iterativ, deoarece șir de operațiuni sunt în mod inerent greu de vectorizare.Ar trebui să utilizați df.iterrows()
. Deși iterarea rând-cu-rând nu este în mod special eficientă din Seria de obiecte trebuie să fie creat.
În timp ce iterrows()
este o opțiune bună, uneori itertuples()
poate fi mult mai rapid:
df = pd.DataFrame({'a': randn(1000), 'b': randn(1000),'N': randint(100, 1000, (1000)), 'x': 'x'})
%timeit [row.a * 2 for idx, row in df.iterrows()]
# => 10 loops, best of 3: 50.3 ms per loop
%timeit [row[1] * 2 for row in df.itertuples()]
# => 1000 loops, best of 3: 541 µs per loop
Puteți folosi, de asemenea, df.se aplică()
pentru a itera peste rânduri și accesează mai multe coloane pentru o funcție.
def valuation_formula(x, y):
return x * y * 0.5
df['price'] = df.apply(lambda row: valuation_formula(row['x'], row['y']), axis=1)
Puteți scrie propriile iterator care implementează namedtuple
from collections import namedtuple
def myiter(d, cols=None):
if cols is None:
v = d.values.tolist()
cols = d.columns.values.tolist()
else:
j = [d.columns.get_loc(c) for c in cols]
v = d.values[:, j].tolist()
n = namedtuple('MyTuple', cols)
for line in iter(v):
yield n(*line)
Acest lucru este direct comparabilă cu pd.DataFrame.itertuples`. Am'm cu scopul de a efectua aceeași sarcină cu mai multă eficiență.
Pentru dataframe cu funcția mea:
list(myiter(df))
[MyTuple(c1=10, c2=100), MyTuple(c1=11, c2=110), MyTuple(c1=12, c2=120)]
Sau cu pd.DataFrame.itertuples`:
list(df.itertuples(index=False))
[Pandas(c1=10, c2=100), Pandas(c1=11, c2=110), Pandas(c1=12, c2=120)]
Un program de testare Noi de testare a face toate coloanele disponibile și subsetting coloane.
def iterfullA(d):
return list(myiter(d))
def iterfullB(d):
return list(d.itertuples(index=False))
def itersubA(d):
return list(myiter(d, ['col3', 'col4', 'col5', 'col6', 'col7']))
def itersubB(d):
return list(d[['col3', 'col4', 'col5', 'col6', 'col7']].itertuples(index=False))
res = pd.DataFrame(
index=[10, 30, 100, 300, 1000, 3000, 10000, 30000],
columns='iterfullA iterfullB itersubA itersubB'.split(),
dtype=float
)
for i in res.index:
d = pd.DataFrame(np.random.randint(10, size=(i, 10))).add_prefix('col')
for j in res.columns:
stmt = '{}(d)'.format(j)
setp = 'from __main__ import d, {}'.format(j)
res.at[i, j] = timeit(stmt, setp, number=100)
res.groupby(res.columns.str[4:-1], axis=1).plot(loglog=True);
Uneori, un model util este:
# Borrowing @KutalmisB df example
df = pd.DataFrame({'col1': [1, 2], 'col2': [0.1, 0.2]}, index=['a', 'b'])
# The to_dict call results in a list of dicts
# where each row_dict is a dictionary with k:v pairs of columns:value for that row
for row_dict in df.to_dict(orient='records'):
print(row_dict)
Care duce la:
{'col1':1.0, 'col2':0.1}
{'col1':2.0, 'col2':0.2}
La bucla toate rândurile într-un dataframe
și utilizare valorile din fiecare rând convenabil, namedtuples
poate fi convertit la `ndarray lui. De exemplu:
df = pd.DataFrame({'col1': [1, 2], 'col2': [0.1, 0.2]}, index=['a', 'b'])
Iterarea peste rânduri:
for row in df.itertuples(index=False, name='Pandas'):
print np.asarray(row)
rezultate în:
[ 1. 0.1]
[ 2. 0.2]
Vă rugăm să rețineți că, dacă index=True
, indicele este adăugat ca primul element al tuplu, care poate fi de dorit pentru unele aplicații.
Atât pentru vizualizarea și modificarea valorilor, mi-ar folosi iterrows()
. Într-o buclă și prin utilizarea tuplu despachetarea (a se vedea de exemplu: eu, rând
), eu folosesc " row "pentru vizualizarea doar de valoarea și de a folosi" i " cu loc
metodă atunci când vreau pentru a modifica valorile. După cum se menționează în răspunsurile precedente, aici tu nu ar trebui să modifice ceva ce sunt iterarea peste.
pentru că, rând din df.iterrows(): dacă row['O'] == 'Old_Value': df.loc[i,'O'] = 'New_value'
Aici " row " în buclă este o copie rând, și nu o vedere de aceasta. Prin urmare, ar trebui să NU scrie ceva de genul rând['O'] = 'New_Value'
, aceasta nu va modifica DataFrame. Cu toate acestea, puteți utiliza i
și loc
și specificați DataFrame pentru a face munca.
Există o modalitate de a repeta arunca rânduri în timp ce obținerea o DataFrame în schimb, și nu o Serie. Eu nu't vedea cineva de menționat faptul că puteți trece index ca o listă de rând să fie returnate ca un DataFrame:
for i in range(len(df)):
row = df.iloc[[i]]
Notă utilizarea de console duble. Acesta întoarce o DataFrame cu un singur rând.
Puteți face, de asemenea, `numpy de indexare pentru o viteza mai mare up. L's nu iterarea dar funcționează mult mai bine decât repetare pentru anumite aplicații.
subset = row['c1'][0:5]
all = row['c1'][:]
De asemenea, poate doriți să-l arunce la o matrice. Acești indici/selecții ar trebui să acționeze ca Numpy tablouri deja dar am fugit în probleme și nu este nevoie să arunce
np.asarray(all)
imgs[:] = cv2.resize(imgs[:], (224,224) ) #resize every image in an hdf5 file
Există atât de multe moduri de a repeta peste rânduri în panda dataframe. Un mod foarte simplu și intuitiv este :
df=pd.DataFrame({'A':[1,2,3], 'B':[4,5,6],'C':[7,8,9]})
print(df)
for i in range(df.shape[0]):
# For printing the second column
print(df.iloc[i,1])
# For printing more than one columns
print(df.iloc[i,[0,2]])
Acest exemplu utilizează iloc de a izola fiecare cifră în cadru de date.
import pandas as pd
a = [1, 2, 3, 4]
b = [5, 6, 7, 8]
mjr = pd.DataFrame({'a':a, 'b':b})
size = mjr.shape
for i in range(size[0]):
for j in range(size[1]):
print(mjr.iloc[i, j])