스택큐힙리스트

팬더 데이터프레임에서 백만 개의 행을 사용하여 행과 이전 행을 비교하는 가장 빠른 방법 본문

카테고리 없음

팬더 데이터프레임에서 백만 개의 행을 사용하여 행과 이전 행을 비교하는 가장 빠른 방법

스택큐힙리스트 2023. 11. 2. 18:17
반응형

 def myJFunc(df):
... # 초기화 jnum 카운터
... jnum = 0;
... # 각 행의 데이터프레임을 반복 (첫 번째 / 제로 제외)
... for i in range(1,len(df)):
... # 사용자가 변경되었는지 확인
... if df.User.loc[i] == df.User.loc[i-1]:
... # 시간이 1 (시간) 이상 증가했는지 확인
... if abs(df.Time.loc[i]-df.Time.loc[i-1])>1:
... # 새로운 열 업데이트
... df['newcol2'].loc[i-1] = 1;
... df['newcol1'].loc[i] = 1;
... # jnum 증가
... jnum += 1;
... # 내용이 변경되었는지 확인
... if df.Col1.loc[i][0] != df.Col1.loc[i-1][0]:
... #이 변경 사항 기록
... df['newcol4'].loc[i-1] = [df.Col1.loc[i-1][0], df.Col2.loc[i][0]];
... # 다른 사용자인가요?
... elif df.User.loc[i] != df.User.loc[i-1]:
... # 새로운 열 업데이트
... df['newcol1'].loc[i] = 1;
... df['newcol2'].loc[i-1] = 1;
... # jnum을 다른 위치에 저장 (여기에는 코드가 포함되어 있지 않음) 및 jnum 재설정
... jnum = 1;

이제 이 함수를 수백만 행에 적용해야 하는데, 그럴 경우 너무 느려서 어떻게 속도를 높일지 알아보려고 합니다. 함수 속도를 향상시킬 수 있는 Cython에 대해 들어보았는데, 제 경험이 전혀 없습니다 (또한 pandas와 python도 처음입니다). 데이터프레임의 두 행을 매개변수로 함수에 전달하고, 이를 Cython을 사용하여 속도를 향상시킬 수 있는지 가능한지, 아니면 함수가 데이터프레임의 한 행만 읽고 쓰는 diff 값을 가진 새로운 열을 생성해야만 Cython을 사용한 이득을 얻을 수 있는지 알고 싶습니다. 다른 속도 향상 팁이 있다면 대단히 감사하겠습니다!


(.loc을 사용하는 경우 .loc, .iloc 및 .ix를 비교해보았을 때, 이것이 약간 더 빠르다는 이유로 현재 사용하고 있습니다)


(또한 실제로의 User 열은 int가 아닌 유니코드이므로 빠른 비교에 문제가 될 수 있습니다)

답변 1

df['time_diff'] = df.groupby('User')['Time'].diff()
df['Col1_0'] = df['Col1'].apply( lambda x: x[0] )
df['Col1_0_prev'] = df.groupby('User')['Col1_0'].shift()
User Time Col1 time_diff Col1_0 Col1_0_prev
0 1 6 [고양이, 개, 염소] NaN 고양이 NaN
1 1 6 [고양이, 양] 0 고양이 고양이
2 1 12 [양, 염소] 6 양 고양이
3 2 3 [고양이, 사자] NaN 고양이 NaN
4 2 5 [어류, 염소, 레머] 2 어류 고양이
5 3 9 [고양이, 개] NaN 고양이 NaN
6 4 4 [개, 염소] NaN 개 NaN
7 4 11 [고양이] 7 고양이 개

앤디가 객체를 저장하는 데 대한 후속 조치로, 여기서 내가 한 것은 리스트 열의 첫 번째 요소를 추출하고 (이에 이동 된 버전도 추가)하는 것이었습니다. 이렇게하면 한 번만 비싼 추출을 수행한 후에는 표준 판다스 방법을 사용할 수 있습니다.

답변 2

판다스는 파이썬에서 데이터 분석 및 조작을 위한 강력한 도구이다. 그러나 수백만 개의 행을 가진 데이터 프레임을 다루는 경우 성능 문제가 발생할 수 있다. 따라서 이러한 대규모 데이터셋에서 효율적으로 이전 행과의 비교를 수행하는 방법을 알아보고자 한다.
판다스 데이터프레임은 행 단위로 접근하여 처리하는 것이 기본 방법이다. 하지만 이와 같은 작업을 수 백만 개의 행에서 반복 작업해야 한다면, 성능 저하가 발생할 수 있다. 따라서 적절한 방법을 사용하여 이전 행과 비교하는 것이 중요하다.
가장 간단한 방법은 for 루프를 사용하여 행을 하나씩 비교하는 것이다. 이 방법은 간단하지만 매우 비효율적이다. 따라서 벡터화된 함수를 사용하여 한 번에 여러 행을 처리하는 것이 더 효율적이다.
판다스에서는 shift() 함수를 사용하여 이전 행을 가져올 수 있다. shift() 함수는 특정 열을 한 번에 한 행씩 순방향 또는 역방향으로 이동시킨다. 이를 활용하여 현재 행과 이전 행을 비교하는 작업을 수행할 수 있다.
또한 diff() 함수를 사용하여 현재 행과 이전 행 간의 차이를 계산할 수도 있다. 이를 통해 특정 열에서의 증가 또는 감소를 확인할 수 있다. 예를 들어, 수익 열을 추가하고 현재 행과 이전 행의 차이를 계산하는 경우, 양수 값은 수익이 증가한 것을 의미하고 음수 값은 수익이 감소한 것을 의미한다.
또 다른 방법은 shift() 및 apply() 함수를 결합하여 복잡한 비교 로직을 구현하는 것이다. apply() 함수를 사용하여 사용자 정의 함수를 각 행에 적용할 수 있다. 이를 활용하여 고도로 유연하고 복잡한 비교 로직을 구현할 수 있다. 하지만 apply() 함수는 느릴 수 있으므로 성능이 중요한 경우에는 신중하게 사용해야 한다.
따라서 수백만 개의 행을 가진 판다스 데이터프레임에서 이전 행과의 비교를 가장 빠르게 수행하는 방법은 shift() 및 diff() 함수를 조합하여 벡터화된 연산을 수행하는 것이다. 이를 활용하면 빠른 속도와 효율적인 메모리 사용을 보장할 수 있다.

반응형
Comments