티스토리 뷰

728x90
반응형

이번 포스팅은 일반 알고리즘을 Pandas를 써서 빠르게 하는 내용입니다.

(LOC를 사용한 특정 Col의 Value 바꾸기)

 

오늘 일하는데, 아래와 같은 상황을 만났습니다.

 

문제의 상황

해당 문제를 단순히 반복문으로 접근하면 아래와 같이 풀이가 가능합니다.

import pandas as pd
Data = pd.DataFrame({"a" : [5,9,7,8,1,2,6,3,7,8,4,9,2,1],
		    "b" : ["A","A","B","D","D","B","A","A","B","D","C","D","C","C"]})
Data["c"] = None

for i in Data.index:
    if Data.at[i,"b"]=="C":
        Data.at[i,"c"] = 1

하지만, 위 경우 Data의 길이가 짧으니 가능합니다.

 

하지만 Data의 Raw의 개수가 100만, 1000만, 1억개가 되면? 기다리다가 늙어죽을지도 모릅니다.

 

그러면 일반적인 Pandas의 LOC를 쓰면 가능할까요?

import pandas as pd
Data = pd.DataFrame({"a" : [5,9,7,8,1,2,6,3,7,8,4,9,2,1],
		    "b" : ["A","A","B","D","D","B","A","A","B","D","C","D","C","C"]})
Data["c"] = None

'''
for i in Data.index:
    if Data.at[i,"b"]=="C":
        Data.at[i,"c"] = 1
'''
#Data[Data.loc[:,"b"]=="C"]
#=>Data[Boolean List]를 활용해서 Data에서 col_b가 C인 Data만 subset
Data[Data.loc[:,"b"]=="C"].loc[:,"c"] = 1
=> "c"의 모든 값은 여전히 None

DataFrame[Boolean]형태로 때어온 Data에 대해서는 Value Change를 해도 원본 Table에 변화가 없어보입니다.

 

Pandas로 손쉽게 SIMD로 빠르게 처리할라 했더니, 마음처럼 되지가 않습니다.

 

이때 사용할 수 있는 방법이 DataFrame[Boolean, "col_nm"] = change_value입니다.

import pandas as pd
Data = pd.DataFrame({"a" : [5,9,7,8,1,2,6,3,7,8,4,9,2,1],
		    "b" : ["A","A","B","D","D","B","A","A","B","D","C","D","C","C"]})
Data["c"] = None

'''
for i in Data.index:
    if Data.at[i,"b"]=="C":
        Data.at[i,"c"] = 1
'''
#Data[Data.loc[:,"b"]=="C"].loc[:,"c"] = 1
#[Data.loc[:,"b"]=="C"][0]
#= Data의 b Col 기준으로 값이 C인 경우 True
#그 외에는 False값 반환
Data.loc[[Data.loc[:,"b"]=="C"][0],"c"] = 1
print(Data)
    a  b     c
0   5  A  None
1   9  A  None
2   7  B  None
3   8  D  None
4   1  D  None
5   2  B  None
6   6  A  None
7   3  A  None
8   7  B  None
9   8  D  None
10  4  C     1
11  9  D  None
12  2  C     1
13  1  C     1

이렇게하면 SIMD를 사용하여 for 반복문은 쓰는것 보다 매우 빠른 결과물을 얻을 수 있습니다.

 

마지막으로 for 반복문과 Pandas 를 활용한 방법의 실행시간을 비교한 결과입니다.(random한 100만개의 raw 생성)

import pandas as pd
import random
import time
Data = pd.DataFrame({"a" : [random.randint(1,100) for i in range(1000000)],
		    "b" : [["A","B","C","D"][random.randint(0,3)] for i in range(1000000)]})
Data["c"] = None

start = time.time()
for i in Data.index:
    if Data.at[i,"b"]=="C":
        Data.at[i,"c"] = 1
print("time :", time.time() - start)
==>time : 12.38511323928833


start = time.time()
Data.loc[[Data.loc[:,"b"]=="C"][0],"c"] = 1
print("time :", time.time() - start)
==>time : 0.06506919860839844

for 반복문은 12.4초, Pandas를 사용한 경우 0.065초로, 약 190배의 속도가 차이나는것을 볼 수 있습니다.

728x90
반응형

'Python 잡지식' 카테고리의 다른 글

Python의 매개변수 전달방식  (0) 2021.03.13
Event Listener의 정체  (0) 2021.03.10
Python의 Thread1  (0) 2021.03.09
여러개의 List를 기준으로 정렬하기  (0) 2021.02.23
특정 List를 기준으로 Data를 정렬하기  (0) 2021.02.21
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
글 보관함