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

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

           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

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



답변

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


답변

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


답변

사용할 수있는 방법은 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 .


답변

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가 제안한대로 루프를 벡터화 알고리즘으로 대체하는 것이 좋습니다.


답변

어쨌든 반복하려는 경우 가장 간단한 방법을 사용하지 않는 이유는 무엇입니까? 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


답변

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


답변

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

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