행 단위로 반복하면서 팬더의 데이터 프레임 업데이트


214

나는 이와 같은 팬더 데이터 프레임을 가지고 있습니다 (꽤 큰 것)

           date      exer exp     ifor         mat  
1092  2014-03-17  American   M  528.205  2014-04-19 
1093  2014-03-17  American   M  528.205  2014-04-19 
1094  2014-03-17  American   M  528.205  2014-04-19 
1095  2014-03-17  American   M  528.205  2014-04-19    
1096  2014-03-17  American   M  528.205  2014-05-17 

이제 행 단위로 반복하고 싶습니다. 각 행을 통과 할 때 각 행의 값은 ifor 일부 조건에 따라 변경 될 수 있으며 다른 데이터 프레임을 찾아야합니다.

이제 반복하면서 이것을 어떻게 업데이트합니까? 그들 중 누구도 효과가 없었던 몇 가지를 시도했습니다.

for i, row in df.iterrows():
    if <something>:
        row['ifor'] = x
    else:
        row['ifor'] = y

    df.ix[i]['ifor'] = x

이러한 접근 방식 중 어느 것도 효과가없는 것 같습니다. 데이터 프레임에서 업데이트 된 값이 표시되지 않습니다.


2
당신이 원하는 것 같아요 df.ix[i,'ifor']. df.ix[i]['ifor']체인 인덱싱이기 때문에 문제가 있습니다 (팬더에서는 신뢰할 수 없음).
Karl D.

1
당신은뿐만 아니라 다른 프레임을 제공 할 수 있습니다 <something>. 코드를 벡터화 할 수 있는지 여부는 그에 따라 다릅니다. 일반적으로 피하십시오 iterrows. 귀하의 경우에는 각 행이 dtype 이기 때문에 반드시 피해야합니다 . objectSeries
Phillip Cloud

조건에 대한 부울 마스크를 작성하고 해당 행을 모두 업데이트 한 다음 나머지를 다른 값으로 설정하는 것이
좋습니다.

iterrows ()를 사용하지 마십시오. 팬더의 역사에서 최악의 안티 패턴을 가능하게합니다.
cs95

답변:


232

df.set_value를 사용하여 루프에 값을 할당 할 수 있습니다.

for i, row in df.iterrows():
    ifor_val = something
    if <condition>:
        ifor_val = something_else
    df.set_value(i,'ifor',ifor_val)

행 값이 필요하지 않으면 단순히 df의 인덱스를 반복 할 수 있지만 여기에 표시되지 않은 행 값이 필요한 경우 원래 for 루프를 유지했습니다.

최신 정보

df.set_value ()는 버전 0.21.0부터 더 이상 사용되지 않습니다. 대신 df.at ()를 사용할 수 있습니다.

for i, row in df.iterrows():
    ifor_val = something
    if <condition>:
        ifor_val = something_else
    df.at[i,'ifor'] = ifor_val

6
pandas.pydata.org/pandas-docs/stable/generated/… , 두 번째 글 머리표 참조 : "2. 반복하는 것을 절대로 수정해서는 안됩니다"
Davor Josipovic

32
우리가 정확히 똑같이 읽었는지 확실하지 않습니다. 내 의사 코드를 보면 반복자의 값이 아니라 데이터 프레임에서 수정 작업을 수행합니다. 반복자 값은 값 / 객체의 인덱스에만 사용됩니다. 실패 할 것은 설명서에 언급 된 이유로 row [ 'ifor'] = some_thing입니다.
rakke

3
명확하게 해 주셔서 감사합니다.
Davor Josipovic

8
이제 set_value도 무시되고 .at (또는 .iat)를 사용해야하므로 루프가 다음과 같이 보입니다. i, 'ifor'] = ifor_val
complexM

2
set_value는 더 이상 사용되지 않으며 향후 릴리스에서 제거 될 예정입니다. 대신 .at [] 또는 .iat [] 접근
자를

75

Pandas DataFrame 객체는 Series of Series로 간주해야합니다. 다시 말해, 열의 관점에서 생각해야합니다. 이것이 중요한 이유는 사용할 때 pd.DataFrame.iterrows행을 Series로 반복하고 있기 때문 입니다. 그러나 이들은 데이터 프레임이 저장하는 시리즈 가 아니므로 반복하는 동안 생성 된 새로운 시리즈입니다. 즉, 할당을 시도하면 편집 내용이 원래 데이터 프레임에 반영되지 않습니다.

자, 이제 그 길을 벗어났습니다 : 우리는 무엇을합니까?

이 게시물 이전의 제안은 다음과 같습니다.

  1. pd.DataFrame.set_value되는 팬더 버전 0.21 추천되지
  2. pd.DataFrame.ix되어 사용되지
  3. pd.DataFrame.loc괜찮지 만 배열 인덱서에서 작동 할 수 있으며 더 잘 할 수 있습니다

내 추천
사용pd.DataFrame.at

for i in df.index:
    if <something>:
        df.at[i, 'ifor'] = x
    else:
        df.at[i, 'ifor'] = y

이것을 다음과 같이 변경할 수도 있습니다.

for i in df.index:
    df.at[i, 'ifor'] = x if <something> else y

의견에 대한 답변

if 조건에 대해 이전 행의 값을 사용해야하는 경우 어떻게해야합니까?

for i in range(1, len(df) + 1):
    j = df.columns.get_loc('ifor')
    if <something>:
        df.iat[i - 1, j] = x
    else:
        df.iat[i - 1, j] = y

if 조건에 대해 이전 행의 값을 사용해야하는 경우 어떻게해야합니까? OG df에 지연 열을 추가 하시겠습니까?
유카

효율성 측면에서, 지연된 열을 추가하는 것보다 접근 방식이 더 좋습니까, 아니면 작은 데이터 집합에 미치는 영향은 무시할 수 있습니까? (<10k rows)
Yuca

조건에 따라서. 지연된 열을 사용하려고합니다. 이 답변은 반복해야 할 경우 수행 할 작업을 보여줍니다. 그러나 반복 할 필요가 없다면 반복하지 마십시오.
piRSquared

또한, stackoverflow.com/q/51753001/9754169에 대한 피드백을 받을 수 있다면 정말 좋을 것입니다 : D
Yuca

이전 대안과 .at []를 대조하기에
좋습니다

35

사용할 수있는 방법은 itertuples()입니다. 튜플의 첫 번째 요소로 인덱스 값을 사용하여 명명 된 튜플로 DataFrame 행을 반복합니다. 그리고에 비해 훨씬 빠릅니다 iterrows(). 의 경우 itertuples()각각 DataFrame에 row포함 되며 값을 설정하는 데 Index사용할 수 있습니다 loc.

for row in df.itertuples():
    if <something>:
        df.at[row.Index, 'ifor'] = x
    else:
        df.at[row.Index, 'ifor'] = x

    df.loc[row.Index, 'ifor'] = x

대부분의 경우 또는 itertuples()보다 빠릅니다 .iatat

감사합니다 @SantiStSupery, 사용하는 .at것보다 훨씬 빠르기 때문에loc .


3
정확한 색인 만 가리 키므로 .loc 대신 .at를 사용하여 성능을 향상시킬 수 있습니다. 이에 대한 자세한 내용은이 질문참조하십시오
SantiStSupery

이상한 생각이지만 df.loc[row.Index, 3] = x작동하지 않습니다. 반면에 df.loc[row.Index, 'ifor'] = x작동합니다!
seralouk

19

df.ix[i, 'exp']=X또는 df.loc[i, 'exp']=X대신에 값을 할당해야합니다 df.ix[i]['ifor'] = x.

그렇지 않으면보기를 작업 중이며 따뜻하게해야합니다.

-c:1: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame. Try using .loc[row_index,col_indexer] = value instead

그러나 확실히 DataFrame@Phillip Cloud가 제안한대로 루프를 벡터화 알고리즘으로 대체하는 것이 좋습니다.


10

어쨌든 반복하려는 경우 가장 간단한 방법을 사용하지 않는 이유는 무엇입니까? df['Column'].values[i]

df['Column'] = ''

for i in range(len(df)):
    df['Column'].values[i] = something/update/new_value

또는 새 값을 이전 값 또는 이와 유사한 값과 비교하려면 목록에 저장 한 다음 끝에 추가하십시오.

mylist, df['Column'] = [], ''

for <condition>:
    mylist.append(something/update/new_value)

df['Column'] = mylist

7
for i, row in df.iterrows():
    if <something>:
        df.at[i, 'ifor'] = x
    else:
        df.at[i, 'ifor'] = y

0

- 를 사용하여 lambda함수 를 사용하는 것이 좋습니다df.apply()

df["ifor"] = df.apply(lambda x: {value} if {condition} else x["ifor"], axis=1)

-3

열에서 MAX 번호를 증가시킵니다. 예를 들어 :

df1 = [sort_ID, Column1,Column2]
print(df1)

내 출력 :

Sort_ID Column1 Column2
12         a    e
45         b    f
65         c    g
78         d    h

MAX = df1['Sort_ID'].max() #This returns my Max Number 

이제 df2에 열을 만들고 MAX를 증가시키는 열 값을 채워야합니다.

Sort_ID Column1 Column2
79      a1       e1
80      b1       f1
81      c1       g1
82      d1       h1

참고 : df2에는 처음에 Column1 및 Column2 만 포함됩니다. 우리는 Sortid 열을 생성하고 df1에서 MAX를 증분해야합니다.

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