히비스서커스의 블로그

[Pandas] dataframe에서 데이터 읽기 속도 관련 (feat. values vs iloc) 본문

Programming/Python

[Pandas] dataframe에서 데이터 읽기 속도 관련 (feat. values vs iloc)

HibisCircus 2024. 11. 20. 12:24
728x90

파이썬에서 대용량 dataframe을 다루다 보면 시간이 오래걸릴 때가 있다. 대용량부터는 데이터를 효율적으로 읽어들이는 방법을 써야 시간을 아낄 수 있다. 이번에도 아니나 다를까 시간이 오래 걸려 코드를 개선하였는데 훨씬 더 빨라졌다.

 

 

기존 코드에 작성한 코드는 다음과 같다.

    def __getitem__(self, idx):
        item = {}
        img_path = self.df.values[idx,1].replace('./','/data/nas_data/Public/dacon_mai/')
        image = cv2.imread(img_path)
        image = self.transform(image)
        reduced_matrix = self.df.values[idx,2:].astype(float)
        
        item['image'] = image.float() #color channel first, then XY
        item['reduced_expression'] = torch.tensor(reduced_matrix).float()  #cell x features (3467)

        return item

 

dataframe에서 values 메서드를 통해 값을 가져왔다. 이때는 astype을 통해 데이터 형식 변환하였고 tensor로 변환해주었다.

 

개선된 코드는 다음과 같다.

    def __getitem__(self, idx):
        item = {}
        img_path = self.df.iloc[idx,1].replace('./','/data/nas_data/Public/dacon_mai/')
        image = cv2.imread(img_path)
        image = self.transform(image)
        reduced_matrix = self.df.iloc[idx,2:]
        
        item['image'] = image.float() #color channel first, then XY
        item['reduced_expression'] = torch.tensor(reduced_matrix,dtype=torch.float32) #cell x features (3467)

        return item

 

dataframe에서 iloc 메서드를 통해서 읽어왔고 tensor로 변환해줄 때, dtype을 활용하였다.

 

속도가 유의미하게 빨라졌다. 10분 정도 소요되던 것이 10초도 안걸린다.

 

그 이유가 궁금하여 챗지피티한테 물어보았다.

 

코드를 수정한 후 속도가 빨라진 이유는 df.values와 df.iloc의 데이터 접근 방식 차이에서 비롯됩니다.

1. df.values 사용 시 느려지는 이유
df.values[idx, 2:]: df.values는 DataFrame의 데이터를 numpy.ndarray로 반환합니다. 이 방식은 전체 데이터셋을 NumPy 배열로 변환한 후 데이터를 가져오기 때문에, DataFrame에서 값을 추출할 때 항상 DataFrame의 모든 값을 한꺼번에 메모리에 로드하게 됩니다.데이터가 크면, 전체 데이터를 한 번에 가져오는 작업이 비용이 많이 듭니다.특히, **Pandas의 기본 데이터 타입(예: float64)**과 PyTorch의 torch.float32 간에 변환 작업이 추가적으로 필요할 수 있습니다.6992 x 3469 크기의 큰 데이터를 처리할 때, 매번 df.values로 NumPy 배열을 생성하고 나서 그 배열에서 값을 가져오면 메모리와 성능에서 부담이 커집니다.

2. df.iloc 사용 시 성능이 향상된 이유
df.iloc[idx, 2:]: iloc는 DataFrame에서 정수 기반 인덱싱을 사용하여 필요한 부분만 추출합니다. 이 방식은 데이터를 바로 Pandas의 내부 구조에서 접근하기 때문에, values처럼 전체 DataFrame을 메모리에 로드하지 않고, 필요한 부분만 접근합니다.더 효율적으로 데이터에 접근할 수 있습니다.또한, dtype=torch.float32를 사용하여 데이터 타입을 생성 시점에서 명시적으로 설정하므로, 불필요한 타입 변환 과정이 줄어듭니다.

주요 차이 요약:
**df.values**는 전체 DataFrame을 numpy.ndarray로 변환한 후 데이터에 접근하므로 전체 데이터를 메모리에 로드하는 데 시간이 많이 걸릴 수 있습니다.**df.iloc**는 정수 인덱스 기반으로 필요한 부분만 선택하므로 메모리 효율성이 높고, 데이터 접근 속도가 빨라집니다.
따라서, 수정된 코드에서는 iloc을 사용해 필요한 부분만 선택하고, 타입을 생성 시점에서 명시함으로써 더 효율적인 처리가 가능해져 속도가 빨라진 것입니다.

 

 

df.values는 df를 매번 불러오는데 df.iloc는 부분만 불러와서 속도가 더 빨라졌던 것이다. 이왕이면 values가 아닌 iloc를 활용하여 사용하자!

728x90