Org 테이블 스프레드시트
≡ 목차 (Table of Contents)
Org Mode의 테이블은 간단한 스프레드시트(Spreadsheet) 기능을 제공한다. 테이블의 각 셀을 이용해 계산을 하는 것 등인데 마치 엑셀이나 Numbers, 구글 독스에서 제공하는 스프레드시트(Spreadsheet)와 유사하다. 사용법이 좀 어렵긴 하지만 그래도 재미있으니 한번 살펴보자.
참고로 이 글에서 언급하는 단축키는 Doom Emacs 기준이다. 물론 일부 단축키는 바닐라 Emacs와 동일할 수도 있다.
테이블
일단 아래와 같은 테이블을 만들었다고 가정해보자.
| Kind | Price | Ideal | Earning | |-------+-------+-------+---------| | Book | 100 | 99 | | | Apple | 256 | 30 | | | Coke | 4 | 9 | | |-------+-------+-------+---------| | | | | |
위 테이블을 이용해 계속 살펴보자.
셀 정보 확인하기
스프레드시트에서는 행과 열에 고유번호가 있듯이 테이블에도 고요 번호 시스템이 있다.
우선 커서를 아래 []
위치에 놨다고 가정하자.
| Kind | Price | Ideal | Earning | |-------+-------+-------+---------| | Book | 100 | 99 | [] | | Apple | 256 | 30 | | | Coke | 4 | 9 | | |-------+-------+-------+---------| | | | | |
커서 위치의 셀 주소(?)를 파악하기 위해 C-c ?
혹은 SPC m b h
키를 눌러보면 하단 미니 버퍼에 커서가 있는 위치의 주소를 표시해준다.
line @2, col $4, ref @2$4 or D2
여기서 @2$4
라는 값이 커서가 위치한 셀의 위치를 한 번에 나타내는 셀 주소다. 복잡하지만 이런 표현 방법을 알아야 이후의 내용을 진행할 수 있다.
셀의 고유번호를 확인하는 다른 방법도 알아보자. C-c }
키를 누르면 테이블 헤더에 주소 정보가 토글된다.
1| Kind | Price | Ideal | Earning | I*1 |$1-----+$2-----+$3-----+$4-------| 2| Book | 100 | 99 | [] | 3| Apple | 256 | 30 | | 4| Coke | 4 | 9 | | I*2 |$1-----+$2-----+$3-----+$4-------| 5| | | | |
이 정보를 통해서 $1부터 $4까지 표시되는 것이 칼럼(행, Column) 번호이고 골뱅이가 로우(열, Row) 번호임을 유추할 수 있다.
Lisp 함수 실행시켜 보기
위의 마지막 표에서 커서가 위치한 곳인 []
위치에서 아래와 같은 내용을 입력해보자.
:='(- @2$3 $2$2);N
위 텍스트를 입력하고 끝에서 TAB
키를 눌러주면 뭔가 변화가 생긴다.
| Kind | Price | Ideal | Earning | |-------+-------+-------+--------------------| | Book | 100 | 99 | -1 | | Apple | 256 | 30 | | | Coke | 4 | 9 | | |-------+-------+-------+--------------------| | | | | | #+TBLFM: @2$4='(- @2$3 @2$2);N
커서가 있던 위치에 -1
이라는 값이 찍힌 것을 볼 수 있다. 즉 위에서 입력한 코드는 3번 칼럼의 값($3)에서 2번 컬럼의 값($2)을 빼라는 의미이고 그래서 커서 위치에 그 결과인 -1 이 찍힌 것이다.
그렇다면 해당 코드의 의미를 이렇게 이해할 수 있다:
:=
은 이 셀에는 이후에 나오는 내용으로 치환시킨다는 의미다.'
는 Lisp의 quote 함수다.(- @2$3 @2$2)
는 Lisp 코드로 2열 3행의 값에서 2열 2행의 값을 뺀다는 의미다. 제일 앞의-
가 바로 빼기 함수다.;N
은 Lisp 코드의 끝을 의미한다.
몇몇 내용은 아마도 Emacs Lisp을 좀 알아야 이해가 될 것 같다.
그 외에 표의 하단에 아래와 같은 특수한 내용이 추가되어 있는 것이 보인다.
#+TBLFM: @2$4='(- @2$3 @2$2);N
#+
로 시작하는 표기는 Org Mode 문서에서 프로퍼티를 표현할 때 사용하는 기호다. 아마도 방금 입력했던 식을 다르게 표시한 것으로 유추된다.
그렇다면 이 `#+` 부분을 약간 고치면 아마 식의 내용이 자동으로 바뀔 것 같다. TBLFM의 내용을 아래처럼 고쳐보자.
#+TBLFM: $4='(- $3 $2);N
수정한 뒤에는 C-c C-c
키를 눌러야 반영된다. 그러면 아래처럼 내용이 바뀐다.
| Kind | Price | Ideal | Earning | |-------+-------+-------+---------| | Book | 100 | 99 | -1 | | Apple | 256 | 30 | -226 | | Coke | 4 | 9 | 5 | |-------+-------+-------+---------| | | | | 0 | #+TBLFM: $4='(- $3 $2);N
4행의 값은 3행 빼기 2행의 값이다 라는 것을 정의했다. 이제 자동으로 입력된 값 외의 다른 값을 수정하면 제일 오른쪽 행의 값이 자동으로 바뀐다. 그야말로 엑셀 같은 스프레드시트가 되었다. 불행히도 마지막 열 까지 데이터가 입력되어 버린 것은 좀 이상하긴 하지만…
사칙연산 사용해보기
이제 Lisp 코드 말고 calc
를 통해 제공되는 계산기 기능을 써보자. 앞의 내용과 비슷한 기능을 시험해 보기 위해 다시 테이블을 처음의 모양으로 리셋시켰다.
| Kind | Price | Ideal | Earning | |-------+-------+-------+---------| | Book | 100 | 99 | [] | | Apple | 256 | 30 | | | Coke | 4 | 9 | | |-------+-------+-------+---------| | | | | |
커서 위치도 여전히 []
로 표시한 부분인 Earning 칼럼의 첫 로우에 있다. 이 위치에서 이제 아래와 같은 내용을 입력해보자.
=$3-$2
내용이 아까 보다는 단순하다. 어쨌든 입력을 하고 TAB
키를 누르는 순간 비슷하게 아래와 같이 표시된다.
| Kind | Price | Ideal | Earning | |-------+-------+-------+---------| | Book | 100 | 99 | -1 | | Apple | 256 | 30 | | | Coke | 4 | 9 | | |-------+-------+-------+---------| | | | | | #+TBLFM: $4=$3-$2
뭔가 더 쉽고 직관적인 문법의 명령어를 썼는데 결과는 아까와 비슷해 보인다. 하지만 여기서 끝이 아니다.
이제 살짝 마법을 써보자. 하단의 #+TBLFM
쪽으로 커서를 가져한 후 C-c C-c
키를 눌러보자.
| Kind | Price | Ideal | Earning | |-------+-------+-------+---------| | Book | 100 | 99 | -1 | | Apple | 256 | 30 | -226 | | Coke | 4 | 9 | 5 | |-------+-------+-------+---------| | | | | 0 | #+TBLFM: $4=$3-$2
갑자기 자동으로 계산되는 영역이 늘었다. Earning 칼럼 전체에 데이터가 자동으로 계산되어 들어갔다.
입력한 명령어의 차이에서 :
오퍼레이터 존재의 의미가 이해가 갈 것 같다. :=
오퍼레이터는 현재 셀에만 함수를 적용한다는 의미이고, =
오퍼레이터는 이 행이나 열 전체에 해당 함수를 적용한다는 의미일 것 같다.
비록 가장 아래쪽에 이상한 데이터가 하나 들어가긴 했지만…
합계 구하기
이제 Price와 Ideal 수치 합계를 한번 계산해보자. 제일 아래의 빈 로우에 값을 채워 넣을 예정이다. 여전히 커서는 []
로 표시한 위치에 있다고 가정하자.
| Kind | Price | Ideal | Earning | |-------+-------+-------+---------| | Book | 100 | 99 | -1 | | Apple | 256 | 30 | -226 | | Coke | 4 | 9 | 5 | |-------+-------+-------+---------| | | [] | | 0 | #+TBLFM: $4=$3-$2
이번엔 조금 다른 방법을 써서 편집해보자. SPC m b e
키를 누르면 하단에 별도의 버퍼가 열리면서 여기에 해당 셀에 입력할 값을 별도로 입력할 수 있다. 이 특수 버퍼에 아래와 같은 내용을 입력해보자.
:=vsum(@2$2..@4$2)
미니버퍼에 잘 표시가 되어있지만 위의 것을 입력한 후 C-c C-c
키를 눌러야만 입력한 내용이 셀에 반영된다. 뭐… 수동으로 입력하는 거랑 별반 차이는 없겠지만 말이다.
이제 할 일은 입력된 내용 위에서 TAB
키를 눌러보는 것이다.
| Kind | Price | Ideal | Earning | |-------+-------+-------+---------| | Book | 100 | 99 | -1 | | Apple | 256 | 30 | -226 | | Coke | 4 | 9 | 5 | |-------+-------+-------+---------| | | 360 | | 0 | #+TBLFM: $4=$3-$2::@5$2=vsum(@2$2..@4$2)
아래에 Price 합계가 표시되었다. 그리고 제일 하단에 TBLFM 항목에도 방금 입력한 것과 비슷한 명령이 추가되었다.
입력했던 내용 자체는 앞서 살펴본 것과 비슷하다. 다만 vsum
함수가 특별한데, 이 함수는 지정된 범위 내의 데이터를 합하기 위한 calc 패키지의 함수다.
이제 남은 빈 곳도 채우기 위해 직접 TBLFM 코드를 수동으로 수정해보자.
#+TBLFM: $4=$3-$2::@5=vsum(@2..@4)
vsum
입력 인자에서 모든 행을 대상으로 하도록 수정했다. 이제 다 고쳤으니 C-c C-c
를 눌러보자.
| Kind | Price | Ideal | Earning | |---------------------+-------+-------+---------| | Book | 100 | 99 | -1 | | Apple | 256 | 30 | -226 | | Coke | 4 | 9 | 5 | |---------------------+-------+-------+---------| | Book + Apple + Coke | 360 | 138 | -222 | #+TBLFM: $4=$3-$2::@5=vsum(@2..@4)
뭔가 다 채워지긴 했는데 이상하다.🤦
계산 영역 제한하기
위 결과에서 좌측 하단의 이상한 것(?)을 지워보자. 방금 명령으로 입력되어 버린 모든 내용을 초기화하기 위해 제일 아래 로우 각 셀의 내용을 수동으로 다 지웠다.
그리고 TBLFM의 가장 마지막 항목을 아래처럼 고쳐봤다.
#+TBLFM: $4=$3-$2::@5$2..@5$4=vsum(@2..@4)
그리고 TBLFM 위에서 C-c C-c
를 눌러보자.
| Kind | Price | Ideal | Earning | |-------+-------+-------+---------| | Book | 100 | 99 | -1 | | Apple | 256 | 30 | -226 | | Coke | 4 | 9 | 5 | |-------+-------+-------+---------| | | 360 | 138 | -222 | #+TBLFM: $4=$3-$2::@5$2..@5$4=vsum(@2..@4)
이상한 Book + Apple + Coke
라는 이상한 데이터가 사라졌다.
원리는 간단하다. 위에서 사용한 코드는 값이 들어가는 부분을 영역으로 표현했다는 점을 잘 보자. @5$2..@5$4
까지만 vsum의 결과를 적용하겠다는 의미로 사용했다.
이상한 경고 메시지가 뜨긴 하는데 뭐 잘 되었으니 무시하자.😏
어쨌거나 이제 우리는 완벽한(?) 테이블 스프레드시트를 하나 만들었다. 참 먼 길이었다. 역시 구글 스프레드시트나 Numbers를 쓰는게 현명할 것 같다.
calc 함수 목록
아래 함수는 스프레드시트 연산에 사용할 수 있는 다양한 함수들이다. 모든 것을 정리한 것은 아니고 일단 정보를 구한 것만 정리한다.
exp(c)
지수(exponential)log(c)
loglog10(c)
log10sqrt(c)
루트(SQRT, Square-Root)vcor(v1, v2)
상관계수(correlation)vcount(v)
개수vcov(v1, v2)
공분산(covariance)vlen(v)
길이(length)vmax(v)
최댓값(maximum)vmean(v)
평균(average)vmedian(v)
중간값vmin(v)
최솟값(minimum)vprod(v)
곱(product)vsdev(v)
표준편차(standard deviation)vsum(v)
합계vvar(v)
분산(variance)