2017-10-05 1 views
2

필자는 파이썬 데이터 프레임을 반복 처리하고 매우 느리다는 것을 알았습니다. 나는 판다 스에서 모든 것을 벡터화하려고 시도하지만,이 경우 반복적으로 반복 할 필요가 있음을 이해합니다 (또는 벡터화가 가능하면 어떻게해야하는지 명확하지 않습니다).이전 행을 참조하면서 pandas 데이터 프레임을 반복하는 방법은 무엇입니까?

논리는 간단합니다. 두 개의 열 "A"와 "B"와 결과 열 "신호"가 있습니다. A가 1이면 신호를 1로 설정하고 B가 1이면 신호를 0으로 설정합니다. 그렇지 않으면 신호는 이전과 동일합니다. 즉, 열 A는 "켜짐"신호이고 ​​열 B는 "꺼짐"신호이고 ​​"신호"는 상태를 나타냅니다.

def signals(indata): 
    numrows = len(indata) 
    data = pd.DataFrame(index= range(0,numrows)) 
    data['A'] = indata['A'] 
    data['B'] = indata['B'] 
    data['signal'] = 0 


    for i in range(1,numrows): 
     if data['A'].iloc[i] == 1: 
      data['signal'].iloc[i] = 1 
     elif data['B'].iloc[i] == 1: 
      data['signal'].iloc[i] = 0 
     else: 
      data['signal'].iloc[i] = data['signal'].iloc[i-1] 
    return data 

예시 입력/출력 : 여기서

내 코드

indata = pd.DataFrame(index = range(0,10)) 
indata['A'] = [0, 1, 0, 0, 0, 0, 1, 0, 0, 0] 
indata['B'] = [1, 0, 0, 0, 1, 0, 0, 0, 1, 1] 

signals(indata) 

출력 :

A B signal 
0 0 1 0 
1 1 0 1 
2 0 0 1 
3 0 0 1 
4 0 1 0 
5 0 0 0 
6 1 0 1 
7 0 0 1 
8 0 1 0 
9 0 1 0 

이 간단한 로직은 dataframe에서 실행 46초 컴퓨터를 얻어 무작위로 생성 된 데이터가있는 2000 행

답변

0

을 할 수있는 모든 반복 할 필요 없어요. numpy에서 0의 배열을 만든 다음 배열에 반복 논리를 적용했습니다. 그런 다음 데이터 프레임의 열에 배열을 썼습니다. 46초 반대로 랜덤 데이터 2000 행 dataframe에서

def signals3(indata): 
    numrows = len(indata) 
    data = pd.DataFrame(index= range(0,numrows)) 

    data['A'] = indata['A'] 
    data['B'] = indata['B'] 
    out_signal = np.zeros(numrows) 

    for i in range(1,numrows): 
     if data['A'].iloc[i] == 1: 
      out_signal[i] = 1 
     elif data['B'].iloc[i] == 1: 
      out_signal[i] = 0 
     else: 
      out_signal[i] = out_signal[i-1] 


    data['signal'] = out_signal 

    return data 

,이 (1000 배 빠른 ~) 만 43 밀리 초 걸린다.

데이터 프레임 열 A와 B를 계열에 할당 한 다음 해당 계열을 반복하는 변형도 시도했습니다. 이것은 조금 더 빨랐습니다 (27 밀리 초). 그러나 대부분의 속도 저하는 데이터 프레임에 대한 서면으로 나타납니다.

coldspeed와 djk의 답변이 모두 내 솔루션 (약 4.5ms)보다 빠르지 만 실제로는 최적이 아닐지라도 실제로는 시리즈를 반복합니다.

2
df['signal'] = df.A.groupby((df.A != df.B).cumsum()).transform('head', 1) 

df 
    A B signal 
0 0 1  0 
1 1 0  1 
2 0 0  1 
3 0 0  1 
4 0 1  0 
5 0 0  0 
6 1 0  1 
7 0 0  1 
8 0 1  0 
9 0 1  0 

논리는 여기 AB 사이의 불평등에 따라 그룹으로 시리즈를 나누어 포함, 모든 그룹의 값은 A에 의해 결정됩니다.

+0

팬더가이 논리 게이트 연산을 처리하는 방법을 관찰하는 것은 흥미 롭습니다. 나는이 알고리즘이 작동한다는 사실을 아직도 감추고 있습니다. –

+0

이것은 정말 깔끔한 것입니다. 조금 더 설명하면 될까요? – DJK

+0

이것은 흥미로운 해결책이지만, 더 복잡한 반복을 위해 그 논리를 독자적으로 생각해 낼 수는 없습니다. 정말이 유형의 문제에 대한 처리 시간을 줄이기 위해 간단하고 쉽게 복제 할 수있는 방법을 찾고 있습니다. – karakumy

1

당신은 당신이 내 문제에 대한 가장 간단한 대답은 그것을 통해 반복하면서 dataframe에 쓸 것이 었습니다 어떤 부울 색인

#set condition for A 
indata.loc[indata.A == 1,'signal'] = 1 
#set condition for B 
indata.loc[indata.B == 1,'signal'] = 0 
#forward fill NaN values 
indata.signal.fillna(method='ffill',inplace=True) 
관련 문제