데이터 꿈나무
[Python_ts2] 여러 폴더 내의 파일 정보 가져오기 (os.walk) 본문
안녕하세요~ 저번 포스팅 때 os.path.split과 os.path.splitext에 대해서 포스팅을 했었는데요,
이후에 새로운 과제를 진행하게 되어 이 주제로 포스팅 해보려고 해요:)
이번 주제는 상위폴더 아래 여러 하위폴더 내에 있는 파일 정보를 가져오는 방법입니다!
저번 포스팅이 궁금하신 분들은 아래 링크를 클릭해주세요~!
https://risingdata.tistory.com/63
[Python] os.path.split과 os.path.spiltext 알기
안녕하세요~! 오늘은 os.path로 파일 경로 다루는 법을 포스팅 해보려고 해요. 저도 os는 많이 다뤄보지 않아서 자세한 내용은 몰랐는데, 이번에 인턴하면서 알게 되어서 공부 겸 포스팅하려고 합
risingdata.tistory.com
우선 필요한 모듈을 임포트 해줍니다.
그리고 정보를 가져올 파일이 있는 상위 폴더 경로를 filepath에 저장해줍니다.
저희가 가져올 정보는 날짜, 라벨러 번호, 파일 이름, 파일 경로, 제조사 정보입니다.
이런 정보를 저장할 빈 리스트가 필요하기 때문에, data라는 빈 리스트를 생성해줍니다.
from pydicom import dcmread
from pydicom.data import get_testdata_file
import pydicom
import numpy
from glob import glob
import os
import pandas as pd
# 파일 경로
filepath = 'D:/dicom_data_example'
# 정보를 담을 빈 리스트
data = []
# base_folder = 'dicom_data_example'
여러 폴더 내 파일 정보를 가져오기 위해서는, 상위폴더 아래 하위폴더들을 다 하나씩 돌아가면서 정보를 가져와야겠죠?
그러기 위해서 필요한 함수가 바로 os.walk입니다.
📌 os.walk 란?
os.walk는 Python 프로그래밍 언어의 os 모듈에서 제공되는 함수 중 하나입니다.
이 함수는 파일 및 디렉토리 구조를 탐색하고 특정 디렉토리 아래의 모든 하위 디렉토리와 파일을 반복적으로 검색하는 데 사용됩니다.
os.walk 함수를 사용하면 디렉토리 트리를 순회하며 파일 및 디렉토리에 대한 정보를 얻을 수 있습니다.
import os
for root, directories, files in os.walk(directory_path):
# root: 현재 디렉토리의 경로
# directories: 현재 디렉토리의 하위 디렉토리 목록
# files: 현재 디렉토리에 있는 파일 목록
# 여기에서 필요한 작업을 수행합니다.
이제 코드를 살펴볼텐데요, 위에서 filepath = 'D:/dicom_data_example' 이렇게 filepath에 경로를 할당해주었죠?
반복문과 os.walk를 통해 아래 코드와 같이 모든 하위 폴더의 파일을 반복적으로 검색해나갈 것입니다.
첫번째 줄 같은 경우에는 path에 현재 디렉토리의 경로, _에 현재 디렉토리의 하위 디렉토리 목록, file에 현재 디렉토리에 있는 파일 목록이 들어가게 될 것입니다.
현재 폴더 형식이 어떻게 구성되어 있는지 먼저 알려드리겠습니다.
'D:/dicom_data_example' 폴더 안에 '230901', '230915', '230922' 폴더가 있고,
'230901'에는 'labeller1', 'labeller2', 'labeller3'폴더가 있으며,
'230915'에는 'labeller3', 'labeller4', 'labeller5', 'labeller6',
'230922'에는 'labeller7' 이런식으로 구성되어 있습니다.
그리고 각 라벨러 폴더 안에는 dicom파일이 있으며, 이 dicom파일에 있는 정보들을 불러오려는게 저희 목표입니다.
✅ 라벨러 정보 가져오기
os.path.basename(path)를 이용하면 폴더 경로에서 폴더 이름(마지막 부분)을 추출하는 데 사용됩니다. 이 함수를 사용하면 폴더의 전체 경로에서 폴더 이름 부분만 추출할 수 있습니다.
for path, _, file in os.walk(filepath): # _와 file이 있는 path, path아래에 있는 폴더들, path아래에 있는 파일들
for file_name in file:
labeller_folder = os.path.basename(path)
✅ 파일 경로 가져오기
os.path.join을 이용해서 반복문의 os.walk를 통해 얻어진 path와 file_name을 join합니다.
그러면 file_path = D:\dicom_data_example\230901\labeller 1\CA_201215.dcm 와 같이 출력될 것입니다.
file_path = os.path.join(path, file_name) # file_path = D:\dicom_data_example\230901\labeller 1\CA_201215.dcm
✅ manufacturer 정보 가져오기
위에서 가져온 파일 경로를 이용해서 이 경로에 있는 manufacturer 정보를 가져올 것 입니다.
저희는 dicom파일을 가져와야 하기 때문에 dicom파일 정보를 가져오는 함수인 pydicom.dcmread를 사용할 것입니다.
manufacturer = pydicom.dcmread(file_path).Manufacturer를 하면 정보가 가져와집니다.
## manufacturer정보 가져오기
manufacturer = pydicom.dcmread(file_path).Manufacturer
✅ date 정보 가져오기
먼저 path를 보면, path = 'D:/dicom_data_example\\230901\\labeller 1' 이런식으로 되어 있습니다.
path 안에 date의 정보가 있는 게 보이시나요?
그러면 저희는 여기에서 날짜 정보만 가져오기 위해서 어떻게 하면 좋을까요?
바로 날짜 정보 앞뒤로 붙어있는 D:/dicom_data_example\\과 \\labeller 1 를 제거하면 됩니다.
둘 다 뭔가 익숙하지 않나요?
D:/dicom_data_example 는 filepath = 'D:/dicom_data_example' 에서 봤고,
labeller 1 는 위에서 라벨러 정보를 가져온 labeller_folder 변수에 저장되어 있습니다.
따라서, 아래 코드와 같이 replace함수를 이용해서 날짜 정보만 추출해낼 수 있습니다.
## date 정보 가져오기
# path = 'D:/dicom_data_example\\230901\\labeller 1'
# filepath = 'D:/dicom_data_example'
# labeller_folder = 'labeller 1'
date = path.replace(filepath, '') # -> \\230901\\labeller 1
date = date.replace(labeller_folder, '') # -> \\230901\\
date = date.replace('\\', '') # -> 230901
마지막으로, 가져온 정보들을 초반에 만들었던 빈 리스트인 data에 append해주어 정보를 저장해줍니다.
file_info = {
'date':date,
'labeller': labeller_folder,
'file name': os.path.splitext(file_name)[0], # ( '파일이름', '.dcm(확장자)' )[0] -> '파일이름'
'file path': file_path,
'manufacture': manufacturer
}
data.append(file_info) # for문이 돌아가면서 각 변수의 정보들 저장
df = pd.DataFrame(data)
# df.to_csv('task2.csv')
df
결과 테이블은 다음과 같습니다.


전체 코드
from pydicom import dcmread
from pydicom.data import get_testdata_file
import pydicom
import numpy
from glob import glob
import os
import pandas as pd
# 파일 경로
filepath = 'D:/dicom_data_example'
# 정보를 담을 빈 리스트
data = []
base_folder = 'dicom_data_example'
for path, _, file in os.walk(filepath): # _와 file이 있는 path, path아래에 있는 폴더들, path아래에 있는 파일들
for file_name in file:
labeller_folder = os.path.basename(path)
file_path = os.path.join(path, file_name) # file_path = D:\dicom_data_example\230901\labeller 1\CA_201215.dcm
## manufacturer정보 가져오기
manufacturer = pydicom.dcmread(file_path).Manufacturer
## date 정보 가져오기
# path = 'D:/dicom_data_example\\230901\\labeller 1'
# filepath = 'D:/dicom_data_example'
# labeller_folder = 'labeller 1'
date = path.replace(filepath, '') # -> \\230901\\labeller 1
date = date.replace(labeller_folder, '') # -> \\230901\\
date = date.replace('\\', '') # -> 230901
file_info = {
'date':date,
'labeller': labeller_folder,
'file name': os.path.splitext(file_name)[0], # ( '파일이름', '.dcm(확장자)' )[0] -> '파일이름'
'file path': file_path,
'manufacture': manufacturer
}
data.append(file_info) # for문이 돌아가면서 각 변수의 정보들 저장
df = pd.DataFrame(data)
# df.to_csv('task2.csv')
df
※ 오답노트
오답노트를 적어보려고 합니다.
처음에는 아래의 코드처럼 dates를 미리 적어주고, 이중 for문을 돌리면서 하려고 했었습니다. 행이 162개가 나와야 하는데 486개로 3배가 더 나온 것을 확인하였습니다.
dates를 정해둔 것이 문제인가 의심을 하던 중, for date in dates: 반복문을 작성하면 안된다는 것을 깨달았습니다.
이유는 os.walk 함수 자체가 상위폴더에서 하위폴더 전체를 도는 함수이기 때문입니다.
저는 date반복문을 한번 더 돌면서 join이 잘못되게끔 코드를 작성하였습니다.
따라서 'for date in dates:'반복문을 지운 후, 'for path, _, file in os.walk(filepath):' 반복문부터 실행하게 수정해야 합니다.
'''
base_folder = 'dicom_data_example'
dates = ['230901', '230915', '230922']
for date in dates:
date_folder = os.path.join(base_folder, date) for path, _, file in os.walk(filepath):
for file_name in file:
labeller_folder = os.path.basename(path)
...
'''

오늘도 읽어주셔서 감사합니다. 더 좋은 글로 찾아뵙겠습니다.

'Activity > Intern' 카테고리의 다른 글
| [Certi 세미나] 알고리즘 기초 - 그래프 구현과 순환 (0) | 2023.10.14 |
|---|---|
| [Certi 세미나] 알고리즘 기초 - 자료 정렬 (1) | 2023.10.09 |
| [Python_ts1] os.path.split과 os.path.spiltext 알기 (0) | 2023.10.01 |
| [Model Study] SNAPSHOT ENSEMBLE(SSE) (3) | 2023.10.01 |
| [Model Study] MobileNet (0) | 2023.09.30 |