Octave Atelier

코드와 해설을 함께 읽는 학습 문서

Code Detail

main_02_lsh

Signal Processing + Statistics 중심의 Octave 학습 예제

ex-recv/02/02_lsh/main_02_lsh.m

목록으로

코드를 복사해 Octave에서 바로 실행할 수 있습니다.

카테고리

Submission Archive

submission

코드 길이

219

lines

작성자

-

날짜 정보 없음

패키지

signal

pkg load

함수 시그니처

function header_names = get_csv_header_name(filepath)

전체 코드

219 lines

######################################################################################################################

% 주제: 하나의 데이터 세트를 읽어서 대표값과 특징을 계산하고 그리는 연습을 합니다.

% 1. 구글의 2024년도 주가 데이터를 준비하라.
%   1) 첨부 파일: google_data_2024.csv
% 2. 1년치 데이터의 종가에 대해 통계 항목을 계산하라.
%   1) 통계 항목: mean, variance, standard deviation, rms
%   2) 정의식에 의해 직접 계산하고 함수를 작성하라.
%   3) Octave가 제공하는 함수를 사용하여 계산하라.
%   4) 두 계산 결과를 비교하라.
% 3. 같은 데이터에서 30일째 이후부터 직전 30일에 대해서 통계 항목을 계산하고 차트를 그려라.
%   1) 가로축은 날짜 또는 정수 인덱스를 사용한다.
%   2) 직접 만든 함수를 사용하라.

% 주문 1:

% - Octave 프로그램을 작성하여 제출
% - 수신: <sunggyu.won@ecoe.kr>
% - 기간: 2025-03-25 ~ 2025-04-01
% - 이메일 제목에 [Octave] 포함
% - 압축 파일 이름 02_wsg.zip (wsg는 이름 이니셜)
% - 메인 파일 이름은 main_02_wsg.m (wsg는 이름 이니셜)

% 주문 2:

% - 프로그램 작성 순서
% 1. 프로그램 상단에 주석 작성
%    1. 프로그램 설명. 작성자. 작성 날짜
% 2. 입력 변수 준비
%    1. csv 파일을 읽는 함수를 작성
% 3. 연산 실행
%    1. mean, variance, standard deviation, rms를 계산하는 함수를 작성
% 4. 플로팅 변수 준비
% 5. 플로팅 실행

% - 체크 포인트
% - 함수
%    - 직접 계산하는 내용은 굳이 함수로 작성하고 호출하라.
%    - 작성된 함수에 함수 설명, 입력 목록, 출력 목록을 주석으로 기록하라.
%    - 루프 풀어쓰기는 가능하면 벡터 연산으로 축약하라.
% - 변수
%    - 연산 결과를 변수에 저장하라.
%    - 플로팅 변수로서 임시 변수(행렬의 슬라이스, 연산식)를 사용하지 말라.
%    - 지금 사용하지 않을 대량의 데이타는 메모리 변수가 아니라 파일에 저장하라.

######################################################################################################################


# 작성자 : 이성한Y
# 작성 완료 날짜 : '25.03.26 (수)
# 설명 : csv 데이터를 읽고 통계를 계산합니다. 통계는 나만의 통계함수와 octave 내장 통계함수 사용가능.
#       csv 데이터는 컬럼별로 데이터를 별도로 저장하나, 현 데이터는 첫번째 컬럼 Dates 규칙이 어긋나 예외처리. 
#       Window size와 Stride를 주면 Rolling 작업을 하여 시간 흐름에 따른 통계 변화를 plot합니다. 
#       (Function의 경우, 별도의 m파일로 빼내서 쓰진 않았음)



########################################################################################################################################
# 1. 데이터 준비

% Prefare dataset
pkg load signal
work_path = pwd;     % 파일 경로 설정, 알맞게 변경하기 (print work directory: 작업 디렉토리 반환)
filename = 'google_data_2024.csv';
fullpath = fullfile(work_path, filename);  % 파일경로 완성용
name_pattern = "2024stock_%s.m";
fid = fopen(fullpath, "r");




# Function description : get csv file's header name
function header_names = get_csv_header_name(filepath)
    # target input : Header 포함된 csv file (Header 존재 여부 체크 하는건 별도로 안달았음, 필요하면 만들기)
    # target output : Header_name (class : cell) 

    fid = fopen(filepath, "r");     % file identifier 축약 : fid , 열리지 않을 시, -1 반환
    if fid == -1
        error("파일을 열 수 없습니다 : %s", filepath)
    end
    header_line = fgetl(fid);       % 공백 아닌 첫 1줄 읽기
    fclose(fid);

    header_names = strsplit(header_line, ",");
end


cols_name = get_csv_header_name(fullpath);   % (Price, Close, High, Low, Open, Volume), Price는 잘못 표기되었고, Dates가 맞음. 별도처리




% Price data
stock_data = dlmread(filename, ",", 3, 0);
price_data = stock_data(:,2:end);




% Date (String 별도 읽기 필요한 것으로 보임, dlmread는 날짜가 허수로 읽어짐) 
str_data = textscan(fid, "%s %f %f %f %f %f", 'Delimiter', ',', 'Headerlines', 3);      # Headerlines : 3행 건너뛰고 읽기
stock_dates = str_data{1};  % 첫 번째 컬럼은 날짜 (문자열 형식)




% Save separated price data by columns
for i = 1:columns(price_data)
    output_filename = sprintf(name_pattern, cols_name{i+1});
    dlmwrite(output_filename, price_data(:, i), "precision", 10);       % precision : 데이터 숫자 자릿수 저장 옵션, 10 : 자릿수 어디까지 저장할지지
end
% 파일 저장은 Dates 컬럼 예외처리를 위해 별도로 함수 제작 x, 필요시 제작.




% Load Close Price Data
target_col = cols_name{2};   # cols_name : {Price, Close, High, Low, Open, Volume}
target_filename = fullfile(work_path, sprintf(name_pattern, target_col));  % 파일 경로 + 이름
target_price = load(target_filename);




########################################################################################################################################
# 2. 종가 통계 계산

% 1) Calculate stats Using handmade func.(mean, var, std, rms)
function output = my_mean(data)
    % target input : numerical type data (integer, double, complex etc...)
    % target output : mean 
    output = sum(data)/length(data);
end
        
function output = my_var(data)
    % target input : numerical type data (integer, double, complex etc...)
    % target output : variance
    output = sum((data-my_mean(data)).^2)/(length(data)-1);     # 모분산, 표본분산 보정 (N 대신 N-1)
end

function output = my_std(data)
    % target input : numerical type data (integer, double, complex etc...)
    % target output : standard deviation
    output = sqrt(my_var(data));
end

function output = my_rms(data)
    % target input : numerical type data (integer, double, complex etc...)
    % target output : Root mean square
    output = sqrt(sum(data.^2)/length(data));
end



hand_mean = my_mean(target_price);
hand_var = my_var(target_price);
hand_std = my_std(target_price);
hand_rms = my_rms(target_price);
fprintf("\nmy mean : %.2f, \nmy var : %.2f, \nmy std: %.2f, \nmy rms : %.2f\n", hand_mean, hand_var, hand_std, hand_rms);



% 2) Calculate stats Using Octave func. (mean, var, std, rms)
oct_mean = mean(target_price);
oct_var = var(target_price);
oct_std = std(target_price);
oct_rms = rms(target_price);
fprintf("\noct mean : %.2f, \noct var : %.2f, \noct std: %.2f, \noct rms : %.2f\n", oct_mean, oct_var, oct_std, oct_rms);   % var, std 차이 확인




########################################################################################################################################
# 3. Rolling stats plot
window_size = 30;       # Rolling할 window size값
stride=1;       # Data 건너뛸 간격 설정
num_rows = floor((length(target_price) - window_size) / stride) + 1;
stats_data = zeros(num_rows, 4);    % 유효 데이터 사이즈 계산 및 지정



% close_price의 첫 번째 30개의 값을 제외하고 루프 실행
row_idx = 1
for i = window_size:stride:length(target_price)
    window_data = target_price(i-window_size+1:i);

    cal_mean = my_mean(window_data);
    cal_var = my_var(window_data);
    cal_std = my_std(window_data);
    cal_rms = my_rms(window_data);    
 
    stats_data(row_idx, :) = [cal_mean, cal_var, cal_std, cal_rms];
    row_idx = row_idx + 1;
end



# Plot 변수
rolling_dates = stock_dates(30:end);
my_rollmean = stats_data(:,1);
my_rollvar = stats_data(:,2);
my_rollstd = stats_data(:,3);
my_rollrms = stats_data(1:4);


# Plot Decoration
figure("Name", "My Rolling Stats Plot", "NumberTitle", "off");
plot(my_rollmean,';my rolling mean;');
hold on;
grid on;
plot(my_rollvar,';my rolling var;');
plot(my_rollstd,';my rolling std;');
plot(my_rollrms,';my rolling rms;');
title(sprintf('Rolling stats plot (window size = %d, Stride = %d, use data = %s)',window_size , stride, target_col), "FontSize", 16);
hold off;

코드 해설

목적

  • Signal Processing + Statistics 중심의 Octave 학습 예제

입력

  • 파라미터: filepath

출력

  • 반환값: header_names
  • 그래프/figure 출력

실행 흐름

  1. 주제: 하나의 데이터 세트를 읽어서 대표값과 특징을 계산하고 그리는 연습을 합니다
  2. 1. 구글의 2024년도 주가 데이터를 준비하라
  3. 2. 1년치 데이터의 종가에 대해 통계 항목을 계산하라
  4. 4) 두 계산 결과를 비교하라
  5. 3. 같은 데이터에서 30일째 이후부터 직전 30일에 대해서 통계 항목을 계산하고 차트를 그려라
  6. 2. 입력 변수 준비
  7. 3. 연산 실행
  8. - 작성된 함수에 함수 설명, 입력 목록, 출력 목록을 주석으로 기록하라
  9. - 루프 풀어쓰기는 가능하면 벡터 연산으로 축약하라
  10. - 연산 결과를 변수에 저장하라

핵심 함수

  • length
  • plot
  • stats_data
  • data
  • my_mean
  • my_var
  • my_rms
  • my_std

실습 과제

  • 샘플링 주파수나 입력 주파수를 바꿔 스펙트럼 변화를 비교해보세요.
  • 같은 연산을 내장 함수와 사용자 함수 두 방식으로 계산해 오차를 비교해보세요.
  • 질량/감쇠/강성 또는 전달함수 계수를 바꿔 응답 변화를 확인해보세요.

학습 팁

  • 그래프 비교 시 축 범위(XLim/YLim)와 단위를 먼저 고정하면 해석 오류를 줄일 수 있습니다.
  • 입력 파일 경로가 현재 작업 디렉터리 기준인지 먼저 확인하세요.
  • 코드가 길기 때문에 섹션 단위로 실행/검증하면서 읽는 것이 효율적입니다.

같은 카테고리 코드

이전 코드 2024stock_Volume 다음 코드 data_dev