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

나는이 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물체가 무엇 이며 어떻게 그것을 사용할 수 있는지 이해하지 못합니다 .



답변

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


답변

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 이며이 질문에서 끝납니다. 그런 다음 수락 된 답변이 방법을 알려주는 것을보고 반복이 옳지 않은지 먼저 묻지 않고 눈을 감고이 코드를 실행합니다.

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


답변

먼저 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)을 사용하면 일반 튜플이 반환됩니다.

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


답변

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


답변

하지만 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


답변

또한 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.iloc 함수를 사용할 수 있습니다.

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