[MATLAB Data Processing 기초 2] Folder 만들기 및 Navigate to folder - 1 ( cd(), mkdir() )
Confocal microscopy 또는 다양한 실험장비를 사용하면 결과값이 담긴 파일 (*.txt 혹은 *.xlsx 파일 등)이 여러개의
하위 폴더에 저장되는 경우가 있습니다.
예를들어, 'Result' 라는 상위 폴더안에 'day1', 'day2', ...., 'dayn' 라는 하위 폴더가 만들어 지고, 각 하위 폴더에는
'result.txt', 'result.csv' 또는 'result.xlsx' 식의 결과 데이터가 저장되어 있습니다.
만일 모든 데이터를 하나의 파일로 취합하고자 한다면, 하위 폴더의 데이터를 하나하나 열고 데이터를 '복사'하고
특정한 데이터 시트 등에 '붙여넣기' 과정을 반복하여야 합니다.
MATLAB은 이러한 하위 폴더를 검색하는 Navigation 기능과 파일을 읽어들일수 있는 기능을 갖고 있기 때문에
위의 과정을 자동화할 수 있습니다. 지정된 위치에서 하위 폴더들을 차례차례 검색하며 지정된 파일들을
하나하나 열기 또는 편집할 수 있고, 파일의 데이터들을 MATLAB의 workspace로 불러와 데이터 편집이 가능합니다.
이러한 과정을 수행하는 프로그램 만들기를 2개의 글로 나누어, 본 글에서는 사전작업격인 하위 폴더 만들기를
수행하겠습니다. 하위 폴더의 이름이 불규칙적(공란, 대소문자 혼용 등)일 수 있으므로
두 번째 글에서는 Regular expression을 이용해 하위 폴더를 검색하는 Navigation 기능을 설명하겠습니다.
우선 5개의 개체와 10일간의 실험기록을 담은 데이터 파일을 가정하겠습니다.
개체의 이름은 'Animal' 이며 5개의 개체가 대상이므로 'Animal1', 'Animal2', ...., 'Animal5' 등으로 명명하겠습니다.
또한 열흘간의 기록이므로 이름을 'Day1', 'Day2', ...., 'Day10' 으로 정하겠습니다.
각 날짜별로 저장된 데이터의 이름은 'export data.xlsx' 입니다.
예를들어, 하나의 폴더(= 최상위 폴더) 안에 다섯 개체의 상위 폴더('Animal') 가 있고,
각 개체의 폴더안에 10개의 하위 폴더('Day')가 있는것입니다.
(OS system이 Mac, Linux의 경우 상하위 폴더간의 delimiter가 '/' 입니다)
Top Level Folder \ Animal1 \ Day1 \ export data.xlsx
Top Level Folder \ Animal1 \ Day2 \ export data.xlsx
Top Level Folder \ Animal1 \ Day3 \ export data.xlsx
................................................................
하지만 위와같은 상/하위 폴더들은 프로그램에 의해 자동으로 만들어진것이 아닌 사람에 의해 수동으로
만들어졌다고 가정하면 특이사항(human error)이 발생합니다. 폴더이름 첫글자가 대문자가 아닌 소문자 라던가
글자와 숫자 사이에 빈 공간이 있는것 등이 그 예시 입니다. 물론 오타가 발생할 수도 있습니다.
한편 실험도중 예상치 못한 일들로 인해 기록을 저장한 데이터가 2개 이상의 파일로 나뉘어질 수도 있습니다.
이 경우 'export data-trial1.xlsx', 'export data-trial2.xlsx' 등으로 명명할수 있습니다.
(OS system이 Mac, Linux의 경우 상하위 폴더간의 delimiter가 '/' 입니다)
Top Level Folder \ Animal1 \ day 1 \ export data.xlsx
Top Level Folder \ animal1 \ Day2 \ export data-trial1.xlsx
Top Level Folder \ animal1 \ Day2 \ export data-trial2.xlsx
Top Level Folder \ Animal 1 \ Day 3 \ export data.xlsx
................................................................
프로그래밍에 앞서 폴더의 생성조건을 다시 요약하자면,
개체이름: Animal1 부터 Animal5 까지
날짜이름: Day1 부터 Day10 까지
폴더경로: top level folder\Animal\Day\export data.xlsx (OS system이 Windows의 경우)
top level folder/Animal/Day/export data.xlsx ( Mac, Linux의 경우)
예외적인 상황과 사람에 의한 에러는 MATLAB의 랜덤값을 생성하는 rand( ) 명령어에 의해 선택되어 집니다.
각 하위 폴더에 생성되는 데이터('export data.xlsx')는 앞의 "[MATLAB Data Processing 기초 1] Excel file -
불러오기, 저장하기( readtable(), writetable() )" 를 참조하여 생성 합니다.
즉, 4개의 그룹(GroupA 부터 GroupD)이 있으며 각 그룹에는 15명의 키(160cm 부터 200cm 까지)가 랜덤으로써
지정합니다. 단, GroupD의 키는 '0' 으로 초기화 니다.
1) 변수 초기화 및 랜덤값 생성 함수 만들기
개체의 수(animal_range), 날짜 범위(day_range), 저장할 파일의 이름(file_name) 등을 지정합니다.
저장할 데이터 파일이 '-trial1', '-trial2' 로 나뉠수 있으므로 여기서는 확장자인 '.xlsx'를 삽입하지 않았습니다.
workspace의 현재 위치를 최상위 폴더로써 지정하였습니다.
본 글에서 랜덤값을 정밀하게 사용하지 않으므로 간단한 방식으로 예외적인 상황을 만들었습니다.
즉, rand( ) 명령어에 의해 생성된 0 - 1.0 사이의 값이 0.5를 기준으로 예외적인 상황(true) 혹은 일반적인 상황(false)이
되게끔 하였습니다. 밑의 코드에서는 하위 함수 generate_random_flag( )의 반환값으로 정수 0 또는 1으로 설정
하였지만 logical 타입의 값인 true 혹은 false를 설정해도 상관없습니다.
% parameters initialization
animal_range = 1:5; % how many animals
day_range = 1:10; % how many days
topLv_folder = pwd; % get path of top level folder
file_name = 'export data';
function [rnd_flag] = generate_random_flag()
% random flag
% for instance, give space between words/delimiters randomly
if rand(1) <= 0.5
rnd_flag = 1; % true
else
rnd_flag = 0; % false
end
end
2) 상하위 폴더 이름 지정하기
앞서 언급한대로 상/하위 폴더들은 사람에 의해 수동으로 만들어졌다고 가정하여, 폴더이름 첫글자의 대소문자 혼용과
글자와 숫자 사이의 빈 공간 발생등의 human error를 가정합니다. 오타가 발생할 수도 있지만 적용가능 범위가 넓기
때문에 여기서는 가정하지 않겠습니다.
'Animal' 과 'Day' 두가지 경우가 있으므로 하나의 하위 함수로 만들었습니다. 입력 파라메터는 string과 숫자이며,
rand( ) 가 생성한 랜덤값에 의해 예외적인 상황의 적용이 결정됩니다.
예를들어, 입력 파라메터인 str = 'Animal', number = 1, 그리고 space_flag = true, capital_flag = false 이라면
함수의 반환값 name = 'animal 1' 가 됩니다.
function [name] = gen_name(str,number)
% give space between words and number randomly
space_flag = generate_random_flag();
% capitalize first letter
capital_flag = generate_random_flag();
if space_flag % true: space between 'word' and number
if capital_flag % true: capitalize first letter
name = [upper(str(1)),str(2:end),' ',num2str(number)]; % ex: 'Animal 1' or 'Day 1'
else % false: no capitalize
name = [lower(str),' ',num2str(number)]; % ex: 'animal 1' or 'day 1'
end
else % false: no space
if capital_flag % true: capitalize first letter
name = [upper(str(1)),str(2:end),num2str(number)]; % ex: 'Animal1' or 'Day1'
else % false: no capitalize
name = [lower(str),num2str(number)]; % ex: 'animal1' or 'day1'
end
end
end
3) 폴더 만들기 및 상하위 폴더 이동
Workspace 현재의 위치를 최상위 폴더라고 한다면,
1) 개체의 이름을 가진 상위 폴더를 하나 생성하고
2) 하나의 날짜 하위 폴더를 만들어 데이터 파일을 이 하위 폴더안에 저장합니다.
3) 한단계 상위 경로로 이동하여 2)의 과정을 반복합니다.
4) 모든 날짜의 하위 폴더를 작업했다면 최상위 폴더로 이동 합니다.
5) 위의 4가지 과정을 모든 개체에 적용될때 까지 반복합니다.
개체의 이름과 날짜는 하위 폴더인 gen_name( )에 의해 생성됩니다.
어떠한 상황에 의해 기록을 저장한 데이터가 2개 이상으로 나뉘어져 있는 경우 -
예를들어 'export data-trial1.xlsx', 'export data-trial2.xlsx' - 하나의 하위 폴더에 복수개의 데이터를 저장합니다.
폴더를 생성하는 명령어 mkdir( ) 는 정상적으로 폴더 생성이 되었는지 status, msg를 반환하는데,
비정상적인 상황을 처리하는 예외상황을 본 포스트에서는 특별히 고려하지 않았습니다.
Excel 데이터시트 형식의 데이터는 15x4의 160cm - 200cm 사이의 랜덤값을 writetable( ) 명령어 로써
만들어졌으며 일종의 dummy data 이므로 신경쓸것이 없습니다. 앞의 " [MATLAB Data Processing 기초 1] Excel file - 불러오기, 저장하기( readtable(), writetable() ) " 글을 참조하면 되겠습니다.
% set sub folder names & make them on disk
for animal = animal_range
% generate a folder name
% ex: 'Animal 1'/'Animal1'/'animal 1'/'animal 1'
animal_name = gen_name('animal',animal);
% path structure: top level / Animal / Day
[status, msg, msgID] = mkdir(animal_name); % make a folder, ex: 'Animal1'
cd(animal_name); % ex: top level -> 'Animal1' folder
for day = day_range
% generate a folder name
% ex: 'Day 1'/'Day1'/'day 1'/'day 1'
day_name = gen_name('day',day);
% path structure: top level / Animal / Day
[status, msg, msgID] = mkdir(day_name); % make a folder, ex: 'Day1'
animalLv_folder = cd(day_name); % ex: 'Animal1' -> 'Day1' folder
% (optional) give extra info: '-trial1','-trial2', or none
trial_rnd_flag = generate_random_flag();
if trial_rnd_flag % true
target_file_name = [file_name,'-trial1.xlsx']; % ex: 'export data-trial1.xlsx'
target_file_name2 = [file_name,'-trial2.xlsx']; % ex: 'export data-trial2.xlsx'
excel_data_write(target_file_name); % write excel data on disk
excel_data_write(target_file_name2);
else
target_file_name = [file_name,'.xlsx']; % ex: 'export data.xlsx'
excel_data_write(target_file_name); % write excel data on disk
end
cd(animalLv_folder); % ex: 'Day11' -> 'Animal1' folder
end
cd(topLv_folder); % ex: 'Animal1' -> top level folder
end
최상위 폴더에 다섯 개체의 상위 폴더가 생성 되었습니다. 첫 글자가 소문자인 경우, 글자와 숫자 사이에 공백이 들어간
경우도 볼 수 있습니다.
하나의 상위 폴더에 10개의 날짜별 하위 폴더가 생성 되었습니다. 상위 폴더와 마찬가지로 human error에 의한
예외적인 경우가 보입니다.
하나의 하위 폴더에 2개 이상의 결과 데이터 파일이 저장될 수도 있습니다.
모든 하위 폴더에는 Excel 데이터 파일 - 본 포스트에서는 비록 dummy data 이지만 - 이 저장되어 있습니다.
Human error의 가장 빈번한 예로써 '오타'가 있습니다. 폴더이름을 명명할때 주로 마지막 글자 또는
중간의 한글자 정도에 오타를 입력하는 경우가 많습니다.
이를 고려하여 두 번째 글에서는 Regular expression을 이용해 하위 폴더를 검색하는 Navigation 기능을
설명하겠습니다.
마지막으로 본 글에 쓰인 모든 MATLAB 코드는 밑에 표시해 두었습니다.
% parameters initialization
animal_range = 1:5; % how many animals
day_range = 1:10; % how many days
topLv_folder = pwd; % get path of top level folder
file_name = 'export data';
% set sub folder names & make them on disk
for animal = animal_range
% generate a folder name
% ex: 'Animal 1'/'Animal1'/'animal 1'/'animal 1'
animal_name = gen_name('animal',animal);
% path structure: top level / Animal / Day
[status, msg, msgID] = mkdir(animal_name); % make a folder, ex: 'Animal1'
cd(animal_name); % ex: top level -> 'Animal1' folder
for day = day_range
% generate a folder name
% ex: 'Day 1'/'Day1'/'day 1'/'day 1'
day_name = gen_name('day',day);
% path structure: top level / Animal / Day
[status, msg, msgID] = mkdir(day_name); % make a folder, ex: 'Day1'
animalLv_folder = cd(day_name); % ex: 'Animal1' -> 'Day1' folder
% (optional) give extra info: '-trial1','-trial2', or none
trial_rnd_flag = generate_random_flag();
if trial_rnd_flag % true
target_file_name = [file_name,'-trial1.xlsx']; % ex: 'export data-trial1.xlsx'
target_file_name2 = [file_name,'-trial2.xlsx']; % ex: 'export data-trial2.xlsx'
excel_data_write(target_file_name); % write excel data on disk
excel_data_write(target_file_name2);
else
target_file_name = [file_name,'.xlsx']; % ex: 'export data.xlsx'
excel_data_write(target_file_name); % write excel data on disk
end
cd(animalLv_folder); % ex: 'Day11' -> 'Animal1' folder
end
cd(topLv_folder); % ex: 'Animal1' -> top level folder
end
function [rnd_flag] = generate_random_flag()
% random flag
% for instance, give space between words/delimiters randomly
if rand(1) <= 0.5
rnd_flag = 1; % true
else
rnd_flag = 0; % false
end
end
function [name] = gen_name(str,number)
% give space between words and number randomly
space_flag = generate_random_flag();
% capitalize first letter
capital_flag = generate_random_flag();
if space_flag % true: space between 'word' and number
if capital_flag % true: capitalize first letter
name = [upper(str(1)),str(2:end),' ',num2str(number)]; % ex: 'Animal 1' or 'Day 1'
else % false: no capitalize
name = [lower(str),' ',num2str(number)]; % ex: 'animal 1' or 'day 1'
end
else % false: no space
if capital_flag % true: capitalize first letter
name = [upper(str(1)),str(2:end),num2str(number)]; % ex: 'Animal1' or 'Day1'
else % false: no capitalize
name = [lower(str),num2str(number)]; % ex: 'animal1' or 'day1'
end
end
end
function [tb_height] = excel_data_write(file_name)
% create random data of three groups and save data into an excel file
var_names = {'GroupA','GroupB','GroupC','GroupD'}; % variable names
num_ppl = 15; % how many data
num_group = 4; % how many groups
height = zeros(num_ppl,num_group); % data initialization
rnd_height = 160 + (200-160).*rand(num_ppl,num_group-1); % 160-200cm height
height(:,1:num_group-1) = rnd_height(:,1:num_group-1); % record data of the first 3 groups
tb_height = array2table(height,'VariableNames',var_names); % convert array to table
writetable(tb_height,file_name,'Sheet',1,'Range','B2:E18'); % save the data
end