development

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

big-blog 2020. 6. 26. 07:47
반응형

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

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

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

itertuples() 보다 빠르다 iterrows()

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

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

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

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

    반복하는 것을 수정 해서는 안됩니다 . 모든 경우에 해당되는 것은 아닙니다. 데이터 유형에 따라 반복자는보기가 아닌 사본을 리턴하며 이에 대한 쓰기는 효과가 없습니다.

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

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

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

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


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


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를 생성하는 매우 드문 경우에 사용되어야한다.

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

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


루핑보다 빠름 : 벡터화 , 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
result = [f(row[0], ..., row[n]) for row in df[['col1', ...,'coln']].values]

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


명백한 예

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

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

참조를위한 벤치마킹 코드.

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


참고 문헌

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


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

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

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

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

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

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


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

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

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

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

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

To loop all rows in a dataframe and use values of each row conveniently, namedtuples can be converted to ndarrays. For example:

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

Iterating over the rows:

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

results in:

[ 1.   0.1]
[ 2.   0.2]

Please note that if index=True, the index is added as the first element of the tuple, which may be undesirable for some applications.


For both viewing and modifying values, I would use iterrows(). In a for loop and by using tuple unpacking (see the example: i, row), I use the row for only viewing the value and use i with the loc method when I want to modify values. As stated in previous answers, here you should not modify something you are iterating over.

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

Here the row in the loop is a copy of that row, and not a view of it. Therefore, you should NOT write something like row['A'] = 'New_Value', it will not modify the DataFrame. However, you can use i and loc and specify the DataFrame to do the work.


You can also do numpy indexing for even greater speed ups. It's not really iterating but works much better than iteration for certain applications.

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

You may also want to cast it to an array. These indexes/selections are supposed to act like Numpy arrays already but I ran into issues and needed to cast

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

There are so many ways to iterate over the rows in pandas dataframe. One very simple and intuitive way is :

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

This example uses iloc to isolate each digit in the data frame.

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

참고 URL : https://stackoverflow.com/questions/10729210/iterating-row-by-row-through-a-pandas-dataframe

반응형