Pandas의 DataFrame에서 행을 반복하는 방법은 무엇입니까?


1947

나는이 DataFrame팬더에서 :

import pandas as pd
inp = [{'c1':10, 'c2':100}, {'c1':11,'c2':110}, {'c1':12,'c2':120}]
df = pd.DataFrame(inp)
print df

산출:

   c1   c2
0  10  100
1  11  110
2  12  120

이제이 프레임의 행을 반복하고 싶습니다. 모든 행에 대해 열 이름으로 요소 (셀의 값)에 액세스 할 수 있기를 원합니다. 예를 들면 다음과 같습니다.

for row in df.rows:
   print row['c1'], row['c2']

팬더에서 그렇게 할 수 있습니까?

비슷한 질문을 찾았습니다 . 그러나 그것은 나에게 필요한 대답을주지 않습니다. 예를 들어 다음을 사용하는 것이 좋습니다.

for date, row in df.T.iteritems():

또는

for row in df.iterrows():

그러나 나는 row물체가 무엇 이며 어떻게 그것을 사용할 수 있는지 이해하지 못합니다 .


11
df.iteritems ()는 행이 아닌 열을 반복합니다. 따라서 행을 반복하려면 행 ( "T")을 바꾸어야합니다. 즉, 행과 열을 서로 변경합니다 (대각선에 반영). 결과적으로, df.T.iteritems ()를 사용하면 원래 데이터 프레임을 해당 행에 효과적으로 반복 할 수 있습니다.
Stefan Gruenwald

11
이 글을 처음 접했고 팬더 초보자라면, 돌리지 마십시오! 데이터 프레임에 대한 반복은 반 패턴이며, 많은 대기에 익숙해지기 전에는하지 말아야 할 일입니다. 당신이하려는 일에 따라 훨씬 더 나은 대안이있을 수 있습니다 . iter*매우 드문 상황에서 기능을 사용해야합니다. 또한 관련 .
cs95

18
cs95와 달리 데이터 프레임을 반복 해야하는 이유는 완벽하므로 새 사용자는 낙심하지 않아야합니다. 한 가지 예는 각 행의 값을 입력으로 사용하여 일부 코드를 실행하려는 경우입니다. 또한 데이터 프레임이 상당히 작은 경우 (예 : 1000 개 미만의 항목) 성능은 실제로 문제가되지 않습니다.
oulenz

1
@oulenz : 이상한 이유로 API를 설계된 목적 (고성능 데이터 변환)을 사용하여 비행하고 싶다면 내 손님이 되십시오. 그러나 최소한을 사용하지 마십시오 iterrows. DataFrame을 반복하는 더 좋은 방법이 있으며 해당 시점의 목록 목록을 반복 할 수도 있습니다. DataFrames를 반복하는 것 외에는 아무것도하지 않는 지점에 있다면 DataFrame을 사용하는 것이 실제로 이점이 없습니다 (반복하는 것이 유일한 일이라고 가정). 그냥 내 2c.
cs95

7
나는 두 번째 @oulenz. 내가 알 수 pandas있는 한 데이터 세트가 작더라도 csv 파일을 읽는 선택의 여지가 있습니다. API를 사용하여 데이터를 조작하는 것이 훨씬 쉬운 프로그래밍
Chris

답변:


2629

DataFrame.iterrows 는 인덱스와 행을 모두 생성하는 생성기입니다.

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

206
참고 : "iterrows는 각 행에 대해 Series를 반환 하므로 행 전체에 dtype을 유지 하지 않습니다 ." 또한 " 반복중인 것을 수정해서는 안됩니다 ." 에 따르면 팬더 0.19.1 문서
viddik13

3
@ viddik13 감사합니다. 그 때문에 나는 어디에서와 같은 수치 431341610650가 읽혀 지는 경우에 부딪쳤다 4.31E+11. dtype을 보존하는 방법이 있습니까?
Aziz Alto

26
itertuples아래 설명과 같이 @AzizAlto를 사용하십시오 . 또한 참조 pandas.pydata.org/pandas-docs/stable/generated/...
악셀

100
iterrows를 사용하지 마십시오. Itertuples는 더 빠르며 데이터 유형을 보존합니다. 더 많은 정보
James L.

11
에서 문서 "순회 팬더 객체를 통해 느린 일반적으로 대부분의 경우, 행을 통해 수동으로 반복하는 것은 [...] 필요하지 않습니다.". 귀하의 답변은 (질문의 맥락에서) 정확하지만 어디서나 이것을 언급하지 않으므로 그리 좋지 않습니다.
cs95

455

Pandas의 DataFrame에서 행을 반복하는 방법은 무엇입니까?

답변 :하지 마십시오 * !

팬더의 반복은 반 패턴이며 다른 모든 옵션을 다 사용한 경우에만 수행해야합니다. iter이름에 " "가 있는 함수를 수천 행 이상 사용하지 않아야합니다. 그렇지 않으면 많은 대기 에 익숙해 져야합니다 .

DataFrame을 인쇄 하시겠습니까? 사용하십시오 DataFrame.to_string().

무언가를 계산하고 싶습니까? 이 경우 다음 순서로 메소드를 검색 하십시오 (여기 에서 수정 된 목록 ).

  1. 벡터화
  2. Cython 루틴
  3. 목록 이해 (바닐라 for루프)
  4. DataFrame.apply(): i) Cython에서 수행 할 수있는 감소, ii) Python 공간에서 반복
  5. DataFrame.itertuples()iteritems()
  6. DataFrame.iterrows()

iterrowsitertuples(이 질문에 대한 답변에서 많은 득표를 모두) 등 정말 이러한 기능에 대한 유용한 유일 일련의 처리를위한 행 개체 / nametuples를 생성하는 매우 드문 경우에 사용되어야한다.

권한에
대한 이의 제기 반복에 대한 문서 페이지 에는 다음과 같은 커다란 빨간색 경고 상자가 있습니다.

팬더 객체를 반복하는 것은 일반적으로 느립니다. 많은 경우에 행을 수동으로 반복 할 필요가 없습니다 [...].

* 실제로 "하지 말 것"보다 조금 더 복잡합니다. df.iterrows()이 질문에 대한 정답이지만 "Ops를 벡터화"하는 것이 좋습니다. 반복을 피할 수없는 상황이 있음을 인정합니다 (예 : 결과가 이전 행에 대해 계산 된 값에 의존하는 일부 작업). 그러나 라이브러리를 알고 있으면 언제인지 알아야합니다. 반복 솔루션이 필요한지 확실하지 않은 경우에는 그렇지 않을 수 있습니다. 추신 :이 답변을 작성하는 이유에 대해 더 알고 싶다면 맨 아래로 건너 뛰십시오.


루핑보다 빠름 : 벡터화 , Cython

많은 수의 기본 연산과 계산은 팬더 (NumPy 또는 Cythonized 함수)를 통해 "벡터화"됩니다. 여기에는 산술, 비교, (대부분) 축소, 재구성 (예 : 피벗), 조인 및 그룹 별 작업이 포함됩니다. 필수 기본 기능 에 대한 설명서 를 통해 문제에 적합한 벡터화 된 방법을 찾으십시오.

존재하지 않는 경우 사용자 정의 cython 확장을 사용하여 직접 작성하십시오 .


차선책 : 목록 이해 *

1) 사용 가능한 벡터화 된 솔루션이없고, 2) 성능이 중요하지만 코드를 싸이클링하는 번거 로움을 극복하기에 충분히 중요하지 않은 경우 및 3) 요소 별 변환을 수행하려는 경우 목록 이해가 다음 호출 포트가되어야합니다. 귀하의 코드에. 이 증거의 좋은 금액 이 지능형리스트가 충분히 빠른 (심지어 때로는 빨리) 많은 일반 팬더 작업에 있습니다 제안하는가.

공식은 간단합니다.

# 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 - same data type
result = [f(row[0], ..., row[n]) for row in df[['col1', ...,'coln']].to_numpy()]
# iterating over multiple columns - differing data type
result = [f(row[0], ..., row[n]) for row in zip(df['col1'], ..., df['coln'])]

비즈니스 로직을 함수로 캡슐화 할 수 있으면이를 호출하는 목록 이해를 사용할 수 있습니다. 원시 파이썬의 단순성과 속도를 통해 임의로 복잡한 작업을 수행 할 수 있습니다.

Caveats
List 이해는 데이터가 다루기 쉽다고 가정합니다. 즉, 데이터 유형이 일관되고 NaN이없는 것이지만 이것이 항상 보장되는 것은 아닙니다.

  1. 첫 번째 방법은 더 분명하지만 NaN을 처리 할 때는 내장 팬더 방법이 존재하는 경우를 선호하거나 (코너 케이스 처리 논리가 훨씬 우수하기 때문에) 비즈니스 논리에 적절한 NaN 처리 논리가 포함되어 있는지 확인하십시오.
  2. 혼합 데이터 형식을 처리 할 때는 데이터 형식이 암시 적으로 가장 일반적인 형식으로 데이터를 업 캐스트하므로 zip(df['A'], df['B'], ...)대신 반복해야 df[['A', 'B']].to_numpy()합니다. 예를 들어 A가 숫자이고 B가 문자열 인 to_numpy()경우 전체 배열을 문자열로 캐스트합니다. 원하는 문자열이 아닐 수도 있습니다. 다행히 zip열을 함께 ping하는 것이 가장 간단한 해결 방법입니다.

* 위 의 주의 사항 섹션에 설명 된 이유로 YMMV .


명백한 예

두 팬더 열을 추가하는 간단한 예를 통해 차이점을 보여 드리겠습니다 A + B. 이는 벡터화 가능한 연산이므로 위에서 설명한 방법의 성능을 쉽게 대조 할 수 있습니다.

여기에 이미지 설명을 입력하십시오

참조 용 벤치마킹 코드.

그러나 항상 이것이 잘리지 않고 건조하지는 않습니다. 때로는 "작업에 가장 적합한 방법"에 대한 대답은 "데이터에 따라 다릅니다"입니다. 내 조언은 데이터에 정착하기 전에 데이터에 대한 다양한 접근 방식을 테스트하는 것입니다.


추가 자료

* Pandas 문자열 메소드는 시리즈에서 지정되었지만 각 요소에서 작동한다는 의미에서 "벡터화"됩니다. 문자열 연산은 본질적으로 벡터화하기 어렵 기 때문에 기본 메커니즘은 여전히 ​​반복적입니다.


이 답변을 쓴 이유

내가 새로운 사용자들로부터 알게되는 일반적인 경향은 "X를 수행하기 위해 어떻게 df를 반복 할 수 있습니까?"라는 형식의 질문을하는 것입니다. iterrows()for 루프 내에서 무언가를 수행하는 동안 호출 하는 코드를 표시합니다 . 이유는 다음과 같습니다. 벡터화 개념을 도입하지 않은 라이브러리의 새 사용자는 데이터를 반복하여 무언가를 수행 할 때 문제를 해결하는 코드를 구상 할 수 있습니다. DataFrame을 반복하는 방법을 모르는 경우 첫 번째 작업은 Google 이며이 질문에서 끝납니다. 그런 다음 수락 된 답변이 방법을 알려주는 것을보고 반복이 옳지 않은지 먼저 묻지 않고 눈을 감고이 코드를 실행합니다.

이 답변의 목표는 새로운 사용자가 반복이 모든 문제에 대한 해결책 일 필요는 없으며, 더 빠르고 더 빠르고 관용적 인 솔루션이 존재할 수 있으며이를 탐구하는 데 시간을 투자 할 가치가 있음을 이해하는 데 도움이됩니다. 반복 대 벡터화 전쟁을 시작하지는 않지만이 라이브러리의 문제에 대한 솔루션을 개발할 때 새로운 사용자에게 정보를 제공하기를 원합니다.


23
이것은 팬더와 함께 사용해야하는 관용적 기술에 중점을 둔 유일한 답변 이므로이 질문에 가장 적합합니다. 얻가 학습 권리 에 답변을 바로 코드 (대신 바로 에 대답 잘못된 코드를 - 즉, 비효율적하지 않습니다 규모를 너무 특정 데이터에 맞게하는) (일반적으로 데이터) 팬더 학습의 큰 부분이다.
LinkBerest

3
나는 당신이 for 루프에 불공평하다고 생각하지만, 내 테스트에서 목록 이해보다 약간 느리다는 것을 알았습니다. 트릭은 zip(df['A'], df['B'])대신에 루프 오버하는 것입니다 df.iterrows().
Imperishable Night

2
@ImperishableNight 전혀; 이 게시물의 요점은 일반적으로 반복을 비난하는 것이 아니라 iterrows()더 나은 대안이 존재하는 경우, 의 사용을 구체적으로 비난 하고 암시 적으로 반복을 비난하는 것입니다. for루프 자체는 정상이지만 요소 단위로 변환을 반복적으로 수행하는 경우 목록 이해가 더 좋습니다.
cs95

1
@ sdbbs가 있으면 sort_values를 사용하여 데이터를 정렬 한 다음 결과에서 to_string ()을 호출하십시오.
cs95

1
List Comprehensions에서 "여러 열 반복"예제는주의해야합니다. DataFrame.values모든 열을 공통 데이터 형식으로 변환합니다. DataFrame.to_numpy()이것도 마찬가지입니다. 다행히도 우리는 zip몇 개의 열과도 함께 사용할 수 있습니다.
David Wasserman

397

먼저 DataFrame에서 행 을 반복 해야하는지 고려해야합니다. 대안 은 이 답변 을 참조하십시오 .

여전히 행을 반복해야하는 경우 아래 방법을 사용할 수 있습니다. 다른 답변에는 언급되지 않은 몇 가지 중요한 경고에 유의하십시오 .

itertuples() 보다 빠르다 iterrows()

그러나 문서에 따르면 (현재 팬더 0.24.2) :

  • iterrows : dtype행마다 일치하지 않을 수 있습니다

    iterrows는 각 행에 대해 Series를 반환하므로 행에 걸쳐 dtype을 유지하지 않습니다 (dtype은 DataFrame의 열에 유지됩니다). 행을 반복하면서 dtype을 유지하려면 itertuples ()를 사용하는 것이 좋습니다. itertuples ()는 값의 명명 된 튜플을 반환하고 일반적으로 iterrows ()보다 훨씬 빠릅니다.

  • iterrows : 행을 수정하지 마십시오

    반복하는 것을 수정 해서는 안됩니다 . 모든 경우에 해당되는 것은 아닙니다. 데이터 유형에 따라 반복자는 뷰가 아닌 사본을 리턴하므로 기록에 영향을 미치지 않습니다.

    대신 DataFrame.apply () 를 사용하십시오 .

    new_df = df.apply(lambda x: x * 2)
  • itertuples :

    열 이름이 유효하지 않은 파이썬 식별자이거나 반복되거나 밑줄로 시작하면 위치 이름으로 이름이 바뀝니다. 많은 수의 열 (> 255)을 사용하면 일반 튜플이 반환됩니다.

자세한 내용 은 반복에 대한 팬더 문서 를 참조하십시오.


4
완료 후 오랫동안이 스레드를 읽는 누군가의 작은 질문 : 효율성 측면에서 df.apply ()가 itertuples와 어떻게 비교됩니까?
Raul Guarini

4
참고 : for row in df[['c1','c2']].itertuples(index=True, name=None):행 반복자에 특정 열만 포함하는 것과 같은 것을 말할 수도 있습니다 .
Brian Burns

12
대신 getattr(row, "c1"), 당신은 그냥 사용할 수 있습니다 row.c1.
viraptor

1
나는 getattr(row, "c1")대신 90 %를 사용 row.c1하면 성능상의 이점을 잃어 버리고 itertuples실제로 문자열을 통해 속성에 접근 해야하는 경우 대신 iterrows를 사용해야한다고 확신합니다.
야행성

3
split-apply-combine이 있음을 알고 있었지만 여전히 (질문 상태대로) DataFrame 을 반복해야하기 때문에이 질문에 우연히 빠져 있습니다. 모두가 함께 향상시킬 수있는 고급 스러움을 가지고 numba하고 cython(같은 문서는 "처음 파이썬 항상 가치가 최적화이다"라고). 나는 다른 사람들이 이러한 경고를 언급하지 않기 때문에 다른 사람들이 (때로는 실망스러운) 문제를 피할 수 있도록이 답변을 썼습니다. 누군가를 오도하거나 "그것이 옳은 일이다"라고 말하는 것은 결코 내 의도가 아니었다. 나는 대답을 향상시켰다.
viddik13

201

을 사용해야합니다 df.iterrows(). Series개체를 만들어야하기 때문에 행 단위로 반복하는 것이 특히 효율적이지 않습니다 .


12
DataFrame을 .py를 통해 numpy 배열로 변환하고 배열에서 직접 작동하는 것보다 빠릅니까? 나는 같은 문제가 있지만 numpy 배열로 변환 한 다음 cython을 사용했습니다.
vgoklani

12
@vgoklani 행 단위로 반복하는 것이 비효율적이며 객체가 아닌 numpy 배열이있는 경우 원시 numpy 배열을 사용하는 것이 거의 확실합니다 (특히 행이 많은 배열의 경우). 당신이 절대적으로하지 않는 한 당신은 행에 걸쳐 반복하는 피해야한다
필립 클라우드

7
df.iterrows (), df.itertuples () 및 zip (df [ 'a'], df [ 'b'])의 시간 소비에 대해 약간의 테스트를 수행했으며 다른 결과에 대한 결과를 게시했습니다. 질문 : stackoverflow.com/a/34311080/2142098
Richard Wong

154

하지만 iterrows()좋은 옵션이, 때로는 itertuples()훨씬 더 빨리 될 수 있습니다 :

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

5
두 예제에서 많은 시간 차이는 .iterrows () 명령에 대해 레이블 기반 색인 작성을 사용하고 .itertuples () 명령에 대해 정수 기반 색인 작성을 사용하는 것처럼 보이기 때문에 발생합니다.
Alex

2
재무 데이터 기반 데이터 프레임 (타임 스탬프 및 4x 플로트)의 경우 itertuples가 내 컴퓨터의 iterrow보다 19,57 배 더 빠릅니다. 만 for a,b,c in izip(df["a"],df["b"],df["c"]:거의 동일하게 빠릅니다.
harbun

7
왜 더 빠른지 설명 할 수 있습니까?
Abe Miessler

4
@AbeMiessler는 iterrows()각 데이터 행을 Series로 상자 화하지만 itertuples()그렇지 않습니다.
miradulo

3
열의 순서 df는 사전에서 작성 되므로 실제로는 불확실하므로 row[1]모든 열을 참조 할 수 있습니다. 정수 대 float 열의 시간은 거의 동일하지만 밝혀졌습니다.
브라이언 번즈

88

또한 df.apply()행을 반복하고 함수의 여러 열에 액세스 하는 데 사용할 수 있습니다 .

docs : DataFrame.apply ()

def valuation_formula(x, y):
    return x * y * 0.5

df['price'] = df.apply(lambda row: valuation_formula(row['x'], row['y']), axis=1)

df [ 'price']가 데이터 프레임의 열 이름을 참조합니까? CSV 파일의 여러 열에서 고유 한 값으로 사전을 만들려고합니다. 논리를 사용하여 고유 한 키와 값으로 사전을 만들었으며 TypeError :( " 'Series'개체는 변경 가능하므로 해시 할 수 없습니다", 색인 0에서 발생했습니다 ') 오류가 발생했습니다.
SRS

코드 : df [ 'Workclass'] = df.apply (lambda row : dic_update (row), axis = 1) 줄 끝 id = 0 줄 끝 def dic_update (row) : dic에없는 행 : dic [row] = id id = id + 1
SRS

신경 쓰지 마, 알았어 함수 호출 라인을 df_new = df [ 'Workclass']. apply (같은 것)로 변경
SRS

2
0 축 기본을 갖는 것은 최악
zthomas.nc

9
공지 사항 apply"iteratite는"행을 통해, 오히려 행 방향으로 기능을 적용하지 않습니다. 위의 코드는 당신이 정말로 아닌 경우 일 것입니다 다른 행에 걸쳐 값을 비교할 때, 예를 들어, 필요 반복 및 굴절률들 (즉, 경우에 당신은 아무것도하지만 반복 할 수 없다).
gented

82

다음과 같이 df.iloc 함수를 사용할 수 있습니다.

for i in range(0, len(df)):
    print df.iloc[i]['c1'], df.iloc[i]['c2']

1
나는 그것이 iterrows 또는 itertuples에 찬성하여 이것을 피해야한다는 것을 알고 있지만, 그 이유를 아는 것은 흥미로울 것입니다. 이견있는 사람?
rocarvaj

12
이것은 데이터 유형을 보존하고 이름별로 열을 참조하려는 경우 내가 아는 유일한 유효한 기술입니다. itertuples데이터 형식을 유지하지만 마음에 들지 않는 이름은 제거합니다. iterrows반대입니다.
Ken Williams

6
팬더 데이터 구조의 특질을 통해 단순하고 표현적인 것을하기 위해 몇 시간을 보냈습니다. 결과적으로 읽을 수있는 코드가 생성됩니다.
Sean Anderson

하지만 for i in range(df.shape[0])내 응용 프로그램에 대한 위의 비트까지이 방법을 속도 수도가 iterrows보다 느린 3.5에 대해 여전히 () 접근 방식.
Kim Miller

큰 Datafrmes my_iter = df.itertuples()에서는 메모리를 두 배로 늘리고 복사하는 데 많은 시간이 걸리므로 더 좋습니다 . 동일합니다 iterrows().
Bastiaan

33

행과 열을 반복하는 방법을 찾고 여기에서 끝났습니다.

for i, row in df.iterrows():
    for j, column in row.iteritems():
        print(column)

18

구현하는 자체 반복자를 작성할 수 있습니다 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)

이것은와 직접 비교할 수 pd.DataFrame.itertuples있습니다. 동일한 작업을보다 효율적으로 수행하는 것을 목표로하고 있습니다.


내 기능이있는 주어진 데이터 프레임의 경우 :

list(myiter(df))

[MyTuple(c1=10, c2=100), MyTuple(c1=11, c2=110), MyTuple(c1=12, c2=120)]

또는과 pd.DataFrame.itertuples:

list(df.itertuples(index=False))

[Pandas(c1=10, c2=100), Pandas(c1=11, c2=110), Pandas(c1=12, c2=120)]

포괄적 인 테스트
모든 열을 사용할 수 있도록 설정하고 열을 하위 설정합니다.

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);

여기에 이미지 설명을 입력하십시오

여기에 이미지 설명을 입력하십시오


2
코드를 읽고 싶지 않은 사람들을 위해 : blue line is intertuples, orange line은 yield 블록을 통한 반복자 목록입니다. interrows비교되지 않습니다.
James L.

18

효율적으로 반복하는 방법?

팬더 데이터 프레임을 실제로 반복 해야하는 경우 iterrows () 사용피할 수 있습니다. 다른 방법이 있으며 평소와 iterrows()최고가 아닙니다. itertuples ()는 100 배 더 빠를 수 있습니다.

한마디로 :

  • 일반적으로을 사용하십시오 df.itertuples(name=None). 특히, 고정 된 숫자 열과 255 개 미만의 열이있는 경우. 포인트 (3) 참조
  • 그렇지 않으면 df.itertuples()열에 공백 또는 '-'와 같은 특수 문자가있는 경우를 제외하고 사용 하십시오. 포인트 (2) 참조
  • itertuples()마지막 예를 사용하여 데이터 프레임에 이상한 열이있는 경우에도 사용할 수 있습니다. 포인트 (4) 참조
  • iterrows()이전 솔루션을 사용할 수없는 경우 에만 사용 하십시오. 포인트 (1) 참조

팬더 데이터 프레임에서 행을 반복하는 다른 방법 :

백만 개의 행과 4 개의 열이있는 임의의 데이터 프레임을 생성하십시오.

    df = pd.DataFrame(np.random.randint(0, 100, size=(1000000, 4)), columns=list('ABCD'))
    print(df)

1) 평소 iterrows()는 편리하지만 조금 느립니다.

start_time = time.clock()
result = 0
for _, row in df.iterrows():
    result += max(row['B'], row['C'])

total_elapsed_time = round(time.clock() - start_time, 2)
print("1. Iterrows done in {} seconds, result = {}".format(total_elapsed_time, result))

2) 기본값 itertuples()은 이미 훨씬 빠르지 만 다음과 같은 열 이름에서는 작동하지 않습니다 My Col-Name is very Strange(열이 반복되거나 열 이름을 단순히 파이썬 변수 이름으로 변환 할 수없는 경우이 방법을 피해야합니다).

start_time = time.clock()
result = 0
for row in df.itertuples(index=False):
    result += max(row.B, row.C)

total_elapsed_time = round(time.clock() - start_time, 2)
print("2. Named Itertuples done in {} seconds, result = {}".format(total_elapsed_time, result))

3) itertuples()name = None을 사용 하는 기본값 은 더 빠르지 만 열 당 변수를 정의해야하기 때문에 실제로는 편리하지 않습니다.

start_time = time.clock()
result = 0
for(_, col1, col2, col3, col4) in df.itertuples(name=None):
    result += max(col2, col3)

total_elapsed_time = round(time.clock() - start_time, 2)
print("3. Itertuples done in {} seconds, result = {}".format(total_elapsed_time, result))

4) 마지막으로 명명 된 이름 itertuples()이 이전 지점보다 느리지 만 열당 변수를 정의 할 필요가 없으며와 같은 열 이름으로 작동합니다 My Col-Name is very Strange.

start_time = time.clock()
result = 0
for row in df.itertuples(index=False):
    result += max(row[df.columns.get_loc('B')], row[df.columns.get_loc('C')])

total_elapsed_time = round(time.clock() - start_time, 2)
print("4. Polyvalent Itertuples working even with special characters in the column name done in {} seconds, result = {}".format(total_elapsed_time, result))

산출:

         A   B   C   D
0       41  63  42  23
1       54   9  24  65
2       15  34  10   9
3       39  94  82  97
4        4  88  79  54
...     ..  ..  ..  ..
999995  48  27   4  25
999996  16  51  34  28
999997   1  39  61  14
999998  66  51  27  70
999999  51  53  47  99

[1000000 rows x 4 columns]

1. Iterrows done in 104.96 seconds, result = 66151519
2. Named Itertuples done in 1.26 seconds, result = 66151519
3. Itertuples done in 0.94 seconds, result = 66151519
4. Polyvalent Itertuples working even with special characters in the column name done in 2.94 seconds, result = 66151519

이 기사는 iterrows와 itertuples의 매우 흥미로운 비교입니다.


14

의 모든 행을 반복하려면 dataframe다음을 사용할 수 있습니다.

for x in range(len(date_example.index)):
    print date_example['Date'].iloc[x]

1
이것은 체인 인덱싱입니다. 나는 이것을하지 않는 것이 좋습니다.
cs95

@ cs95 대신 무엇을 추천 하시겠습니까?
CONvid19

이 작업을 수행하려면 df.columns.get_loc을 호출하여 날짜 열의 정수 색인 위치 (루프 외부)를 가져온 다음 내부에서 단일 iloc 색인 호출을 사용하십시오.
cs95

14
 for ind in df.index:
     print df['c1'][ind], df['c2'][ind]

1
큰 데이터 프레임 (예 : 수백만 행)에서 사용될 때이 옵션의 성능은 어떻습니까?
Bazyli Debowski

정직하게, 나는 정확히 모른다. 나는 최고의 대답과 비교할 때 경과 시간이 거의 동일 할 것이라고 생각한다. 두 경우 모두 "for"구성을 사용하기 때문이다. 그러나 경우에 따라 메모리가 다를 수 있습니다.
Grag2015

4
이것은 체인 인덱싱입니다. 이것을 사용하지 마십시오!
cs95

7

때때로 유용한 패턴은 다음과 같습니다.

# 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)

결과 :

{'col1':1.0, 'col2':0.1}
{'col1':2.0, 'col2':0.2}

6

루프에 모든 행 dataframe사용 각 행의 값을 편리하게는 , namedtuples로 변환 할 수 ndarray의. 예를 들면 다음과 같습니다.

df = pd.DataFrame({'col1': [1, 2], 'col2': [0.1, 0.2]}, index=['a', 'b'])

행을 반복 :

for row in df.itertuples(index=False, name='Pandas'):
    print np.asarray(row)

결과 :

[ 1.   0.1]
[ 2.   0.2]

경우 유의하시기 바랍니다 index=True, 인덱스가 튜플의 첫 번째 요소로 추가됩니다 일부 응용 프로그램 바람직하지 않을 수있다.


5

Series가 아닌 DataFrame을 반환하면서 throw 행을 반복하는 방법이 있습니다. 행을 DataFrame으로 반환 할 목록으로 index를 전달할 수 있다고 언급하는 사람은 없습니다.

for i in range(len(df)):
    row = df.iloc[[i]]

이중 괄호 사용에 유의하십시오. 단일 행이있는 DataFrame을 반환합니다.


이것은 정렬 후 데이터 프레임에서 n 번째로 큰 행을 얻는 데 매우 도움이되었습니다. 감사!
Jason Harrison

3

값을보고 수정하기 위해을 사용 iterrows()합니다. for 루프와 tuple unpacking (예 : 참조 i, row)을 사용 row하여 값을 볼 때만 사용하고 값 을 수정하려고 할 때 메소드 i와 함께 사용 loc합니다. 이전 답변에서 언급했듯이 반복하는 것을 수정해서는 안됩니다.

for i, row in df.iterrows():
    df_column_A = df.loc[i, 'A']
    if df_column_A == 'Old_Value':
        df_column_A = 'New_value'  

여기서 rowin 루프는 해당 행의 사본이며,보기는 아닙니다. 따라서와 같은 것을 작성해서는 row['A'] = 'New_Value'안되며 DataFrame을 수정하지 않습니다. 그러나 작업을 수행하기 위해 DataFrame을 사용 i하고 loc지정할 수 있습니다 .


2

응답 파티에 늦었다는 것을 알고 있지만 위의 @ cs95 답변에 추가하고 싶었습니다. 그의 대답에서 그는 팬더 벡터화가 데이터 프레임으로 물건을 계산하는 다른 팬더 방법보다 훨씬 뛰어나다는 것을 보여줍니다.

먼저 데이터 프레임을 numpy 배열로 변환 한 다음 벡터화를 사용하면 팬더 데이터 프레임 벡터화보다 훨씬 빠릅니다 (그리고 데이터 프레임 시리즈로 다시 변환하는 시간 포함).

@ cs95의 벤치 마크 코드에 다음 함수를 추가하면 매우 분명해집니다.

def np_vectorization(df):
    np_arr = df.to_numpy()
    return pd.Series(np_arr[:,0] + np_arr[:,1], index=df.index)

def just_np_vectorization(df):
    np_arr = df.to_numpy()
    return np_arr[:,0] + np_arr[:,1]

여기에 이미지 설명을 입력하십시오


1

numpy더 빠른 속도를 위해 인덱싱을 수행 할 수도 있습니다. 실제로 반복되지는 않지만 특정 응용 프로그램의 반복보다 훨씬 잘 작동합니다.

subset = row['c1'][0:5]
all = row['c1'][:]

배열로 캐스트 할 수도 있습니다. 이 인덱스 / 선택은 이미 Numpy 배열처럼 작동하지만 문제가 발생하여 캐스팅해야했습니다.

np.asarray(all)
imgs[:] = cv2.resize(imgs[:], (224,224) ) #resize every image in an hdf5 file

1

팬더 데이터 프레임의 행을 반복하는 방법은 너무 많습니다. 매우 간단하고 직관적 인 방법은 다음과 같습니다.

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]])

0

이 예제는 iloc을 사용하여 데이터 프레임의 각 숫자를 분리합니다.

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])

0

일부 라이브러리 (예 : 사용하는 Java interop 라이브러리)는 데이터를 스트리밍하는 경우와 같이 한 번에 한 행씩 값을 전달해야합니다. 스트리밍 특성을 복제하기 위해 데이터 프레임 값을 하나씩 '스트리밍'하고 아래에서 작성했습니다.

class DataFrameReader:
  def __init__(self, df):
    self._df = df
    self._row = None
    self._columns = df.columns.tolist()
    self.reset()
    self.row_index = 0

  def __getattr__(self, key):
    return self.__getitem__(key)

  def read(self) -> bool:
    self._row = next(self._iterator, None)
    self.row_index += 1
    return self._row is not None

  def columns(self):
    return self._columns

  def reset(self) -> None:
    self._iterator = self._df.itertuples()

  def get_index(self):
    return self._row[0]

  def index(self):
    return self._row[0]

  def to_dict(self, columns: List[str] = None):
    return self.row(columns=columns)

  def tolist(self, cols) -> List[object]:
    return [self.__getitem__(c) for c in cols]

  def row(self, columns: List[str] = None) -> Dict[str, object]:
    cols = set(self._columns if columns is None else columns)
    return {c : self.__getitem__(c) for c in self._columns if c in cols}

  def __getitem__(self, key) -> object:
    # the df index of the row is at index 0
    try:
        if type(key) is list:
            ix = [self._columns.index(key) + 1 for k in key]
        else:
            ix = self._columns.index(key) + 1
        return self._row[ix]
    except BaseException as e:
        return None

  def __next__(self) -> 'DataFrameReader':
    if self.read():
        return self
    else:
        raise StopIteration

  def __iter__(self) -> 'DataFrameReader':
    return self

사용할 수있는 것 :

for row in DataFrameReader(df):
  print(row.my_column_name)
  print(row.to_dict())
  print(row['my_column_name'])
  print(row.tolist())

그리고 반복되는 행에 대한 값 / 이름 매핑을 유지합니다. 분명히 위에 표시된 것처럼 apply 및 Cython을 사용하는 것보다 훨씬 느리지 만 일부 상황에서는 필요합니다.


0

한마디로

  • 가능하면 벡터화 사용
  • 연산을 벡터화 할 수없는 경우 목록 이해를 사용하십시오.
  • 전체 행을 나타내는 단일 객체가 필요한 경우 itertuples를 사용하십시오.
  • 위의 내용이 너무 느린 경우-swifter.apply를 시도하십시오
  • 여전히 너무 느린 경우-Cython 루틴을 시도하십시오.

이 비디오의 세부 사항

기준 팬더 DataFrame의 행에 대한 반복 벤치 마크

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.