An Introduction to R (translated in Korean)

Table of Contents

An Introduction to R (translated in Korean)

This is an introduction to R (“GNU S”), a language and environment for statistical computing and graphics. R is similar to the award-winning1 S system, which was developed at Bell Laboratories by John Chambers et al. It provides a wide variety of statistical and graphical techniques (linear and nonlinear modelling, statistical tests, time series analysis, classification, clustering, ...).

이 문서에서는 데이터형(data type), 프로그래밍 기본요소들(programming elements), 그리고 통계 모델링(statistical modelling) 및 그래픽(graphics)에 대한 내용을 다룹니다.

이 매뉴얼은 R {No value for ‘VERSION’}을 위하여 작성되었습니다.

Copyright © 1990 W. N. Venables
Copyright © 1992 W. N. Venables & D. M. Smith
Copyright © 1997 R. Gentleman & R. Ihaka
Copyright © 1997, 1998 M. Maechler
Copyright © 1999–2014 R Core Team

Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies.

Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided that the entire resulting derived work is distributed under the terms of a permission notice identical to this one.

Permission is granted to copy and distribute translations of this manual into another language, under the above conditions for modified versions, except that this permission notice may be stated in a translation approved by the R Core Team.


서문

R에 대한 소개를 담고 있는 본 문서는 빌 베너블스(Bill Venables)와 데이비드 스미스(David M. Smith)가 애들레이드 대학(University of Adelaide)에 있을 당시 S와 S-PLUS의 환경(environment)에 대하여 1990년부터 2년간에 걸쳐 작성한 노트를 기초로 하고 있습니다. 우리는 R과 S 프로그램 사이의 다른 점들을 반영하기 위하여 여러번의 작은 수정 및 일부 내용을 확장하였습니다.

우리는 이러한 방법으로 수정된 노트를 재배포할 수 있도록 허락해주고, 오래 전부터 R을 지원해 온 빌 베네블스(Bill Venables)와 데이비드 스미스(David Smith)에게 깊은 감사의 뜻을 전하고자 합니다.

본 문서에 대한 조언과 교정을 언제나 환영하며, R-core@R-project.org로 내용을 보내주시길 부탁드립니다.

문서를 읽기 전에 독자들에게 드리는 말씀

R이 생소한 독자인 경우에 부록 A에 있는 소개세션(introductory session)을 먼저 살펴보시길 바랍니다.아마도 R을 사용하는 방법에 좀 더 익숙해질 뿐만아니라, 실제로 어떤 결과들이 나오는지 바로 알 수 있게 도와줄 것입니다.

많은 사용자들이 주로 그래픽 기능 때문에 R을 찾습니다. 이러한 분들을 위하여 관련 내용을 언제든지 살펴볼 수 있도록 See Graphics (그래픽스) 챕터에 따로 정리해 두었습니다. 따라서, 문서의 내용을 순서대로 모두 소화내가며 따라가지 않아도 괜찮습니다.


1 소개 및 미리 알아두어야 할 내용


1.1 R의 환경 (인바이런먼트 또는 environment)

R은 데이터의 조작(data manipulation) 및 수학적 계산(calculation), 그리고 시각화(graphical display)를 위한 도구들을 한데 묶어놓은 것입니다. 특히 다음과 같은 기능들을 포함하고 있습니다.

환경(“environment”, 인바이런먼트)라는 용어는 다른 종류의 데이터 분석도구들이 어떤 특정한 기능만을 수행하도록 개발된 도구들을 추가함으로서 시스템을 확장하는 것과는 다르게 체계적이고 잘 계획된 하나의 시스템이라는 점을 부각하기 위하여 사용되었습니다.

R은 연구자가 데이터와의 대화를 통하여 분석방법을 개발하는 수단입니다. 이러한 것은 방대한 양의 패키지(package)에 의하여 빠른 속도로 이루어져 왔습니다. 그러나, R로 작성된 대부분의 프로그램들은 어떤 특정 연구자에게 주어진 하나의 구체적인 데이터만을 분석하기 위하여 작성된 것입니다.


1.2 연관된 소프트웨어 및 문서들

R은 벨연구소(Bell Laboratories)에서 근무중이던 릭 벡커(Rick Becker), 존 챔버스(John Chambers), 그리고 앨런 윌크스(Allan Wilks)에 의하여 개발된 S 언어에 의하여 만들어진 것으로 생각할 수 있습니다. 이 언어는 또한 S-PLUS 시스템의 근간을 형성하고 있습니다.

S 언어의 진화과정은 존 챔버스(John Chambers)와 그의 동료들이 쓴 네 권의 책을 통하여 알 수 있습니다. 만약, R에 대해서 가장 기본적인 참고자료를 원한다면 리차드(Richard A.), 베커(Becker, John M.), 챔버스(Chambers), 그리고 앨런(Allan R. Wilks)가 쓴 The New S Language: A Programming Environment for Data Analysis and Graphics이라는 책을 찾아보길 권합니다. 1991년에 배포된 S 언어의 새로운 기능들은 존 챔버스(John M. Chambers)와 트레버(Trevor J. Hastie)에 의하여 편집된 Statistical Models in S이라는 책을 참고하길 바랍니다. methods 패키지에 구현되어 있는 메소드(method)와 클래스(class)는 존 챔버스(John M. Chambers)가 저술한 Programming with Data을 토대로 하고 있습니다. 더 자세한 내용들은 See References (참고문헌)장에 있는 참고문헌을 살펴보시길 바랍니다.

이미 시중에는 R을 이용한 데이터 분석과 통계학에 관련된 많은 서적들이 있습니다. 또한, S/S-PLUS의 사용을 위하여 작성된 문서들을 참고하는 것 역시 R을 사용하는데 도움이 될 수 있습니다. 그러나, S을 이용하여 구현한 것들간의 차이를 반드시 기억하고 있어야만 합니다. 이에 관해서는 See What documentation exists for R? in The R statistical system FAQ 이라는 장을 참고하시길 바랍니다.


1.3 R과 통계

Our introduction to the R environment did not mention statistics, yet many people use R as a statistics system. We prefer to think of it of an environment within which many classical and modern statistical techniques have been implemented. A few of these are built into the base R environment, but many are supplied as packages. There are about 25 packages supplied with R (called “standard” and “recommended” packages) and many more are available through the CRAN family of Internet sites (via https://CRAN.R-project.org) and elsewhere. More details on packages are given later (see ‘Packages’).

가장 고전적인 통계(classical statistics) 방법부터 최근에 개발된 많은 방법들을R에서 사용될 수 있습니다. 그러나, 이런 것들을 찾는 것은 사용자의 몫입니다.

S (이 문서에서는 R)과 다른 주요 통계 시스템들 사이에는 철학적인 면에서 중요한 다른 점이 존재합니다.S를 이용한 통계분석(statistical analysis)은 보통 일련의 절차로 수행되며, 각 과정에서 얻어진 결과들은 객체(objects)의 형태로 저장되게 됩니다.예를들어, SAS 또는 SPSS를 이용하여 회귀분석(regression) 또는 판별분석(discriminant analysis)을 수행한 경우 분석 과정 중에 생성된 모든 결과를 한번에 보여주는 반면, R은 최소한의 결과만을 출력해주고 생성된 결과들을 적합한 객체의 형태로 저장하여 차후에 이를 활용할 수 있는 추가적인 R 함수들과 함께 사용할 수 있도록 합니다.


1.4 R과 윈도우 시스템

R을 사용하는 가장 손쉬운 방법은 윈도우 시스템(windowing sytem, 즉 두 개이상의 서로 다른 데이터를 여러 개의 창을을 띄어 한 화면에 표시해 주는 시스템)을 사용하는 그래픽 워크스테이션(graphics workstation)을 이용하는 것입니다. 이 문서는 이러한 기능을 활용할 수 있는 사용자들을 위하여 작성되었습니다. 우리는 때때로 특히 X 윈도우 시스템에서 R을 사용하는 것을 위주로 설명하게 되겠지만, 이러한 설명들은 일반적으로 R을 실행할 수 있는 다른 체제에서도 동일하게 적용하게 됩니다.

대부분의 사용자들은 이따금 운영체제(operating system)와 직접적으로 작업을 해야 할 필요가 있을 것입니다. 이 문서에서는 주로 UNIX에서 작업하는 것을 가정하고 있습니다. 만약, 윈도우즈(Windows) 또는 OS X에서 R을 사용하는 경우라면 다소 차이가 있을 수 있습니다.

다소 번거로운 기술적인 조정이 필요하긴 하지만 R이 가진 장점들을 최대한 살리기 위하여 워크스테이션을 설정하는 것은 어렵지 않습니다. 그러나, 본 문서에서는 이러한 내용들을 다루지 않습니다. 만약, 이러한 조정에 어려움을 느끼신다면 주변 전문가에게 도움을 요청하시길 바랍니다.


1.5 R을 대화식으로 사용하기

R 프로그램을 사용할 때 사용자의 명령어를 입력을 기다린다는 의미의 프롬프트(prompt)를 볼 수 있습니다. 이 프롬프트에 대한 기본설정은 ‘>’으로 되어 있습니다. 이 표시는 UNIX에서의 쉘 프롬프트(shell prompt)와도 동일하기도 합니다. 그러나, 다른 모양의 R의 프롬프트를 지정하여 사용할 수도 있습니다. 우리는 이 문서에서 내용의 명확성을 위하여 UNIX의 쉘 프롬프트는 ‘$’를 이용하여 표시하도록 하겠습니다.

UNIX에서 R을 사용하는 경우 다음과 같은 방법으로 실행시킬 수 있습니다:

  1. 먼저 작업을 하게 될 work라고 하는 디렉토리를 생성합니다. 이 디렉토리는 R을 이용하면서 사용하게 될 데이터 파일들을 보관하게 됩니다. 이러한 이유로 이를 작업 디렉토리(working directory)라고 합니다.
    $ mkdir work
    $ cd work
    
  2. 아래의 명령어를 입력하여 R 프로그램을 시작합니다.
    $ R
    
  3. 이제부터 R 명령어들을 사용할 수 있습니다 (추후에 보게 될 것입니다).
  4. R 프로그램을 종료하기 위해서는 다음의 명령어를 사용합니다.
    > q()
    

    이때 현재의 R 세션에서 작업하던 데이터를 저장할 것인지에 대해서 확인하게 됩니다. 일부 시스템에서는 대화상자(dialog box)를 통하여 이것을 묻게 될 수도 있는데 주로 일반텍스트(text) 형식으로 yes(예), no(아니오), 또는 cancel(취소)가 보여질 것입니다. 이때 첫글자를 이용하여 종료전에 데이터를 저장할 것인지, 저장하지 않고 종료할 것인지, 혹은 다시 작업중인 R 세션으로 돌아갈 것인지 선택할 수 있습니다. 저장된 데이터는 다음에 사용될 R 세션에서 다시 사용할 수 있습니다.

이렇게 프로그램을 종료 한 뒤 새로운 R 세션을 시작하는 것은 간단합니다.

  1. 위에서 해 보았던 것과 같이 work라는 작업디렉토리를 생성하고 다음과 같이 프로그램을 시작할 수 있습니다:
    $ cd work
    $ R
    
  2. R 프로그램을 사용하고 난 뒤, 세션의 맨 마지막에서 q() 명령어를 이용하여 종료할 수 있습니다.

윈도우즈 환경에서 R을 사용하기 방법은 기본적으로 UNIX에서 R을 사용하는 방법과 동일합니다. 먼저 작업디렉토리로 사용될 폴더(folder)를 생성한뒤, Start In 메뉴에서 R 바로가기를 생성합니다. 이제 생성된 아이콘을 더블클릭함으로서 R을 실행할 수 있습니다.

1.6 소개 세션(introductory session)

R을 사용하는데 좀 더 빠르게 익숙해지길 희망하는 독자라면 제일 먼저 A sample session이라는 부록에 있는 소개세션(introductory session)을 따라해보기를 적극 권장합니다.


1.7 함수(functions)와 기능(features)에 대한 도움말 사용하기

R은 UNIX에서 man 명령어를 이용하여 도움말을 찾는 것과 유사한 기능을 가지고 있습니다. 예를 들어, solve라는 특정한 이름을 가진 함수에 대한 정보를 알고 싶다면, 다음과 같이 명령해 보도록 합니다.

> help(solve)

다음은 또 다른 방법입니다.

> ?solve

특수문자(special character)에 대해서 알고 싶다면, “문자열(character string)”과 같은 형식으로 반드시 큰따옴표(double quotes) 또는 작은따옴표(single quotes)를 문자열의 앞뒤로 함께 사용해주어야 합니다: 이것은 또한 if, for, 그리고 function과 같은 구문적의미를 가지는 키워드인 경우에도 요구됩니다.

> help("[[")

"It's important"에서 볼 수 있는 것과 같이 인용부호(quote mark)의 종류에 관계없이 문자열을 둘러싼 인용부호는 문자열 내에 포함된 다른종류의 인용부호를 표현할 수 있게 해줍니다. 일반적으로 권장되는 방법은 큰 따음표(double quote marks)를 문자열을 둘러싸는 인용부호로 사용하는 것입니다.

대부분의 경우 설치된 R로부터 HTML의 형식을 가진 도움말을 다음과 같은 방법으로 사용할 수 있습니다

> help.start()

이것은 하이퍼링크를 이용하여 도움말 페이지들을 살펴볼 수 있는 웹브라우저(Web browser)를 실행시킬 것입니다.UNIX에서는 차후에 일어나는 도움말에 대한 요청들은 HTML기반의 도움말 시스템에 보내어집니다.help.start()에 의하여 불러들인 페이지 내에 있는 ‘Search Engine and Keywords’라는 링크는 매우 유용합니다.그 이유는 사용가능한 함수들을 철저하게 검색하는 고수준의 개념목록(high-level concept list)를 포함하고 있기 때문입니다.이것은 또한 시스템을 살펴볼 수 있는 뛰어난 방법이며 어떤 것들이 R에서 제공되는지를 이해할 수 있는 방법이기도 합니다.

help.search 명령어 (다른 표현으로는 ??)는 다양한 방법으로 도움말을 검색하도록 해줍니다. 예를들면, 다음과 같습니다.

> ??solve

더 자세한 내용 및 많은 예제들을 확인하기 위해서는 ?help.search를 입력해 보길 바랍니다.

검색한 도움말과 관련된 예제는 일반적으로 다음과 같은 방법으로 실행해 볼 수 있습니다.

> example(topic)

윈도우즈 버전의 R을 사용하는 경우 도움말을 사용할 수 있는 또 다른 방법이 있습니다:

> ?help

위의 명령어를 입력함으로서 더 자세한 사항을 확인해 볼 수 있습니다.


1.8 R 명령어 및 대소문자의 구분과 같은 내용들

기술적인 측면에서 말하자면 R은 아주 간단한 문법(syntax)를 가진 표현언어(expression language)이라고 할 수 있습니다.UNIX를 기반으로 하는 대부분의 패키지들과 같이 대소문자를 구별(case sensitive)합니다.따라서, Aa는 서로 다른 기호(symbol)로 인식되어 다른 변수를 가리키게 됩니다.R에서 사용할 수 있는 기호들은 사용자의 운영체제 및 R이 현재 실행되고 있는 국가설정(좀 더 기술적으로 말하자면 사용되고 있는 로케일(locale))에 따라 달라질 수 있습니다.기본적으로 모든 알파벳 기호들이 사용가능합니다2 (그리고 일부국가에서는 이것은 엑센트를 가진 문자를 포함하기도 합니다) 또한, ‘.’와 ‘_’을 함께 조합하여 사용할 수 있습니다. 그러나, 변수명은 반드시 ‘.’ 또는 문자(letter)을 이용하여 시작해야 합니다.만약 변수명이 ‘.’로 시작한다면 바로뒤에 이어지는 두번째 문자는 반드시 숫자(digit)가 아닌 문자가 와야 합니다.실제적으로 변수명이 가질 수 있는 길이에는 제한이 없습니다.

기초적인 명령문(commands)은 표현식(expressions) 또는 할당(assignment) 둘 중의 하나로 이루어지게 됩니다. 만약 표현식이 하나의 명령으로서 주어지는 경우, 이 표현식에 대한 평가(evaluate)가 이루어지게 되고 평가된 값은 (특별히 보이지 않도록 처리되지 않는한) 출력되게 됩니다. 그리고 이렇게 평가된 값은 어디에도 저장되지 않고 사라집니다. 할당의 경우 역시 주어진 표현식을 평가한 뒤 평가된 값을 어떤 변수에 저장하도록 넘겨주지만 그 값은 자동으로 출력되지 않습니다.

명령문은 세미콜론(‘;’) 또는 새로운 행(newline, 또는 개행)에 의하여 구분됩니다. 기본적인 명령문들은 한 쌍의 열린 중괄호(‘{’와 ‘}’)에 의하여 하나의 복합표현식(compound expression)으로 묶을 수 있습니다.주석(comments)은 프로그램상의 어느 곳3에나 놓일 수 있습니다.이것은 해쉬마크(hashmark, ‘#’)가 사용된 지점부터 시작하여 라인의 끝부분까지 놓인 모든 것들을 주석처리합니다.

만약 명령문이 한 줄에 모두 다 입력되지 않고 다음 행으로 계속 이어지게 된다면, R은 다른 모양의 프롬프트를 보여줄 것입니다. 아래에 보여지는 기호가 현재 기본적으로 설정되어 있습니다.

+

이 기호는 명령문이 문법적으로 완성될 때까지 두번째 그리고 그 이후의 줄에도 계속 표시되며 입력을 계속해서 받아들이게 됩니다.이 프롬프트는 사용자에 의하여 변경될 수 있습니다.우리는 이 문서에 컨티뉴에이션 프롬프트(continuation prompt)를 생략하고 간단한 들여쓰기(indenting)를 함으로서 명령어가 계속 이어짐(continuation)을 나타낼 것입니다.

콘솔(console) 내에서 입력할 수 있는 명령어 라인(command lines)의 길이는 대략 4095 바이트(bytes)로 제한 됩니다 (문자의 개수를 의미하는 것이 아닙니다). 4


1.9 이전의 명령어를 불러와 수정하기

다양한 버전의 UNIX와 윈도우즈 환경아래에서 실행되는 R은 이전에 사용되었던 명령어들을 다시 불러(recalling)들여 이를 재실행(re-executing) 할 수 있는 매커니즘(mechanism)을 가지고 있습니다. 키보드에서 위 또는 아래로 이동하는 화살표 키를 사용하여 이전에 실행한 명령어들의 이력(command history)을 앞뒤로 살펴볼 수있습니다. 이러한 방법으로 명령어를 선택한 뒤에 좌 또는 우로 이동하는 화살표키를 이용하여 커서를 이동시킵니다. 그리고 DEL를 이용하여 문자를 지우거나 다른 키를 이용하여 입력할수도 있습니다. 더 자세한 내용은 see The command-line editor (명령어라인 편집기) 을 살펴보시길 바랍니다.

UNIX 환경에서는 불러오고 수정하는 기능들을 매우 쉽게 사용자에 맞추어 조정할 수 있습니다. 이러한 조정방법에 대해서는 readline 라이브러리내 관련 매뉴얼 항목에서 찾을 수 있습니다.

더 나아가, 이맥스(Emacs)라는 텍스트 편집기(text editor)는 R과 소통하며 작업을 할 수 있도록 (ESS(Emacs Speaks Statistics)를 통하여) 보다 일반적인 지원 메카니즘(support mechanism)을 제공하고 있습니다. See R and Emacs in The R statistical system FAQ를 살펴보시길 바랍니다.


1.10 파일에 작성된 명령어를 실행하거나 출력방향을 파일로 변경하기

이제 명령어들이 commands.R이라는 외부파일에 저장되어 있고, 이 파일은 work라는 작업 디렉토리(working directory)에 놓여있다고 가정해 봅니다. 이 명령어들은 R 세션내에서 다음의 명령어를 이용하여 언제든지 실행될 수 있습니다.

> source("commands.R")

윈도우즈 환경에서는 File 메뉴에 놓여 있는 Source 항목을 이용하여 동일한 작업을 수행할 수 있습니다.다음에 보여지는 함수 sink는 출력방향을 콘솔로부터 record.lis이라는 외부파일로 변경하여 추후에 생성되는 결과물들이 외부파일에 저장될 수 있도록 해줍니다.

> sink("record.lis")

위와 같이 명령하게 되면 출력의 방향을 다시 콘솔로 향하도록 합니다.

> sink()

1.11 영구적 데이터 생성 및 객체의 제거

R에서 생성하고 다루게 되는 대상들은 객체(objects)라고 알려져 있습니다. 이것은 변수(variables), 숫자로 이루어진 배열(arrays of numbers), 문자열(character strings), 함수(functions)가 될 수도 있고, 또는 이러한 요소들로 이루어진 좀 더 일반적인 구조(structure)가 될 수도 있습니다.

R 세션 내에서 이러한 객체들은 이름(name)을 가지게 됨으로서 생성되거나 저장되어집니다 (우리는 이 과정을 다음 섹션에서 설명할 것입니다).다음의 R 명령어 (또는 ls())를 이용하여 현재 R에서 사용중인 (대부분의) 객체들의 이름을 나열해 볼 수 있습니다.

> objects()

이렇게 현재 사용중인 객체들이 저장되어 있는 공간을 작업공간(workspace)이라고 합니다.

객체들을 삭제하기 위해서는 함수 rm를 사용할 수 있습니다.

> rm(x, y, z, ink, junk, temp, foo, bar)

R 세션 내에서 생성된 모든 객체들은 하나의 파일형태로 영구저장되어 다음 세션에서 사용할 수 있습니다.각 R 세션의 마지막에서 현재 사용중인 모든 객체들을 저장할 수 있는 기회가 사용자에게 주어집니다.만약 객체들을 저장하고자 한다면, 객체들은 .RData5이라는 파일에 쓰여진 뒤 현재의 작업 디렉토리에 저장됩니다. 그리고 세션내에서 사용된 명령어 라인들은 .Rhistory라는 파일에 저장되게 됩니다.

추후에 같은 디렉토리에서 R이 실행된다면 이 파일로부터 이전에 저장된 작업공간(workspace)을 다시 불러오게 됩니다. 이와 동시에 이전 세션에서 사용한 명령어들의 이력 역시 함께 불러들여집니다.

R을 이용하여 여러 개의 분석을 수행하는 경우, 각각의 분석 별로 다른 작업 공간을 이용하는 것이 좋습니다. 그 이유는 분석을 하는 동안 xy 같은 이름을 가진 객체를 생성하는 경우가 흔하기 때문입니다.만약 하나의 분석만을 하는 경우에는 이러한 종류의 이름을 사용하는 것은 종종 의미가 있을 수 있으나, 여러 개의 분석이 같은 디렉토리내에서 이루어지게 되는 경우에는 이러한 이름을 가진 객체들이 각각의 분석에서 어떤 의미를 가지고 사용되는지를 알아차리는 것이 쉽지 않을 수 있습니다.


2 숫자와 벡터에 대한 기초 조작법


2.1 벡터와 할당

R은 이름이 주어진 data structures(데이터 구조)을 이용하여 작업을 하게 됩니다. 이러한 구조를 가진 가장 단순한 형태는 이용하여 라는 것을 기반으로 작동합니다. 가장 단순한 데이터의 구조는 임의의 숫자들의 정렬인 숫자형 (numeric) vector(벡터)입니다.예를들어, 10.4, 5.6, 3.1, 6.4, 그리고 21.7 라는 일련의 숫자로 x라는 이름을 가진 벡터를 생성하기 위해서는 다음과 같은 R 명령어를 입력합니다

> x <- c(10.4, 5.6, 3.1, 6.4, 21.7)

위에서 사용된 표현식을 assignment statement(할당문) 이라고 하며, 여기서 사용된 c()라는 function(함수)는 함수 안에 입력된 여러 개의 임의의 숫자들을 하나로 연결하여 하나의 벡터를 생성합니다. 6

어떤 식(expression) 에서 자체로 있는 하나의 숫자는 길이가 1인 벡터로 취급됩니다.

또한, 띄어쓰기 없이 ‘<’(부등호, 좌측이 우측보다 작음을 표시하는 수학적 기호) 와 ‘-’(음수를 나타내는 기호)를 붙여 써서 만든 ‘<-’ 라는 기호는 할당 연산자(assignment operator)라고 하며, 이 기호의 오른쪽의 표현식에 의해 생성된 값을 갖는 객체를 왼쪽의 이름을 갖도록 지정합니다. 대부분의 경우 ‘=’ 연산자를 같은 작업을 이용하여 할 수 있습니다.

할당(Assignment) 작업은 assign() 함수를 통해서도 이루어질 수 있습니다. 위에서 수행한 것과 동일한 연산을 아래와 같은 방법으로도 할 수 있습니다.

> assign("x", c(10.4, 5.6, 3.1, 6.4, 21.7))

여러분은 할당 연산자 <-를 단순히 assign() 함수와 같은 작업을 하는, 문법적으로는 더 쉬운 방법(short-cut)이라고 생각하셔도 됩니다.

또, 이 할당 연산자의 방향을 바꾸어 아래와 같은 방법으로 사용할 수도 있습니다.

> c(10.4, 5.6, 3.1, 6.4, 21.7) -> x

만약 아래와 같이 할당 연산자를 사용하지 않고 표현식만으로 명령문을 작성하면, 결과물은 출력 되지만, 이 값이 저장되지 않아 다시 불러 낼 수 없습니다. 7.

> 1/x

이제 위의 명령문을 실행하여 (위에서 할당한) x의 다섯 개 숫자의 역수 다섯 개를 출력 해 봅시다.

다음은 여기에 할당 연산자를 적용해보도록 합니다.

> y <- c(x, 0, x)

다음의 할당문은 2개의 x 벡터 사이에 0 을 입력한, 총 11개의 숫자로 구성된 y 라는 새로운 벡터를 생성 합니다.


2.2 벡터 연산

벡터(vector)는 요소 단위의 (element by element) 산술연산 표현식(arithmetic expression)에 사용 가능 합니다. 이 때, 같은 (산술) 표현식 내의 벡터들이 모두 같은 길이를 가질 필요는 없습니다.만약, 벡터들의 길이가 다르면 가장 긴 길이의 벡터를 기준으로, 상대적으로 짧은 길이를 갖는 벡터는 긴 벡터의 길이에 맞추기 위해 그 구성 요소를 재활용(recycled)하여 연산을 수행 합니다. 즉, 더 짧은 길이의 벡터는 가장 긴 벡터와 같은 길이를 같도록 구성 요소를 필요한 만큼 (경우에 따라서는 일부만) 반복 사용 합니다. 특히, 벡터의 길이가 1인 상수(constant)를 벡터와의 연산에 사용할 경우, 이 상수가 벡터의 길이만큼 반복되서 사용 됩니다.

> v <- 2*x + y + 1

위의 예제를 이용해서 설명하면, 다음 명령문을 실행하면 R은 연산을 하기 전 x의 길이를 y에 맞추기 위해서 그 구성 요소를 대략 2.2 번 반복하여 길이 11의 벡터를 만듭니다. 그리고, 2를 x 의 각 요소에 곱한 뒤 (11번의 곱하기 연산이 필요합니다), y의 각 요소와 더하기 연산을 수행합니다. 마지막으로 상수 1과의 더하기 연산 역시 11 번에 걸쳐 수행하며, 이렇게 벡터의 각 요소별로 수행된 연산의 결과는 길이 11의 벡터인 v에 할당 됩니다.

요소 단위 기본 연산자는 +(더하기), -(빼기), *(곱하기), /(나누기), 그리고 ^(자승) 입니다. 일반적인 수학 연산에 자주 사용되는 log, exp, sin, cos, tan, sqrt와 같은 함수가 모두 제공되며, 수학에서 사용하는 것과 동일한 방법으로 사용 됩니다. maxmin는 벡터의 구성요소들 중에서 가장 큰 값과 작은 값을 보여주는 함수입니다. range is a function whose value is a vector of length two, namely c(min(x), max(x)). length(x)는 벡터 x 의 구성요소가 몇 개인가를 알려주며, 이를 보통 x의 길이라고 합니다. sum(x)x의 모든 구성요소들의 합을 구하고자 할 때 사용하고, prod(x)는 모든 구성요소들의 곱을 구할 때 이용됩니다.

R에서는 통계학에서 자주 이용되는 평균과 분산을 계산하는 함수들도 제공됩니다.샘플 평균(sample mean)은 sum(x)/length(x)으로 계산 되는데, mean(x)를 사용해서도 같은 결과를 얻을 수 있습니다. 그리고, 샘플 분산(sample variance)은 아래와 같은 공식을 통해 계산하는데, 이 역시 var(x)를 사용하면 아주 간단하게 계산할 수 있습니다.

sum((x-mean(x))^2)/(length(x)-1)

만약, var() 에 사용되는 입력인자(argument)가 n-by-p 크기의 행렬이라면, 입력인자가p개의 변수들에 대한 n 개의 관측치를 갖는 데이터로 인식되어 p-by-p 크기의 샘플 공분산 행렬(sample covariance matrix)을 계산 합니다.

sort(x)는 벡터 x를 인자로 받아 x의 모든 구성요소들을 오름차순(increasing order, 즉, 작은 값에서 큰 값의 순서로)으로 재배열하여 x와 같은 길이의 벡터를 출력하는 함수 입니다. 이와 비슷한 다른 정렬 함수들 역시 매우 유용하며, 가장 빈번하게 사용되는 예로는 인자로 사용된 x 벡터의 정렬 순서를 확인하기 위해 order() 또는 sort.list()를 사용하는 것을 들 수 있습니다.

maxmin에 여러 개의 벡터가 동시에 입력인수로 사용되었을지라도, 입력된 모든 구성요소들 중에서 최대값과 최소값 하나씩 만을 출력합니다.만약, 여러 개의 벡터 입력인자들을 동시에 입력해서 최대값과 최소값의 병렬(parallel 원한다면, 즉 입력된 여러 개 벡터 인자들을 입력순서 별 최대값 혹은 최소값을 찾는 과정) 원한다면, pmaxpmin 함수를 각각 이용할 수 있습니다. 이 때 반환되는 벡터의 길이는 입력 인자들 중에서 가장 길이가 긴 벡터와 동일합니다. (즉, 길이가 다른 벡터들의 입력시, 길이가 짧은 벡터와 긴 벡터의 비교가 불가능한 구간에서는 오직 비교 가능한 벡터들끼리만 비교해서, 혹은 가장 길기가 긴 벡터의 구성요소를 그대로 출력하게 됩니다).

대부분의 연산에서, 숫자형 벡터(numeric vector)의 구성요소인 “numbers”(숫자)의 종류가 정수(integer)인지, 실수(real)인지, 또는 허수(complex)인지는 중요하지 않습니다. R은 자체적으로 입력된 벡터가 실수인 경우 double precision을 갖는 실수로, 복소수(허수)이면 double precision을 갖는 복소수로 연산을 수행할 수 있습니다.

단, 복소수 연산의 경우, 어느 부분이 허수 부분(copmlex part)인지는 정확히 명시해주어야 합니다.

sqrt(-17)

아래 예시와 같이 허수 부분이 지정하지 않고 명령문을 사용하면, NaN 값과 경고(warning) 메시지가 출력 될 것입니다.

sqrt(-17+0i)

따라서, 다음과 같이 명령문을 입력해야 복소수 연산이 올바르게 수행 됩니다.


2.3 Generating regular sequences (규칙성을 지닌 일련의 숫자들을 생성하기)

R은 수열 (sequence)을 생성하는 다양한 방법을 제공합니다.예를 들면, 1:30이라는 명령어는 c(1, 2, …, 29, 30)과 같은 벡터를 생성합니다. 또 R의 표현식에서는 콜론(colon) 연산자가 다른 어떤 연산 보다 최우선으로 처리됩니다. 예를 들면, 2*1:15c(2, 4, …, 28, 30)과 같은 벡터를 생성합니다. 좀 더 정확한 이해를 위해, n <- 10을 입력한 뒤, 1:n-11:(n-1)로부터 생성되는 두개의 벡터를 비교해보시길 바랍니다.

30:1이라는 명령문은 역순으로 (큰 수부터 작은 수로) 나열된 수열을 생성합니다.

seq() 함수는 수열을 생성하는 좀 더 일반적인 방법 입니다. seq()는 5개의 파라미터를 가질 수 있는데, 이중의 일부만 사용해도 다양한 수열의 생성이 가능합니다.먼저, 처음 두개의 파라미터는 수열의 처음과 마지막 값을 지정합니다.이 두 개의 인자만 지정하면, 콜론 연산자를 사용한 것과 동일한 결과를 얻게 됩니다. 즉, seq(2,10)에 의하여 생성된 수열은 2:10으로부터 생성된 수열과 동일합니다.

R의 다른 많은 함수들처럼 함수 seq()가 사용하는 파라미터들은 반드시 함수에 지정된 순서로 입력되야 하며, 이 지정된 순서를 따를 경우 파라미터의 입력이 언뜻 이상하게 보일 수도 있습니다. 위에서 사용한 예제 seq(1,30)를 통해 설명하면, seq()의 처음 두 파라미터들은 처음 시작값 from=value과 마지막 값 to=value을 각각 의미하기 때문에, seq(1,30), seq(from=1, to=30), seq(to=30, from=1) 모두 1:30으로부터 생성된 수열과 동일한 수열을 생성합니다.seq()의 다음 두개(세번째와 네번째)의 파라미터들은 by=valuelength=value 입니다. by=value는 나열하게 될 숫자들 간의 차이 (step size)를 지정하며, length=value는 나열하게 될 숫자의 길이(length)를 지정합니다. 만약, 이 두가지 모두 지정되지 않는다면, 기본적으로 by=1를 가정한 상태에서 수열을 생성하게 됩니다.

다음의 예시를 살펴봅니다.

> seq(-5, 5, by=.2) -> s3

위 명령어를 실행하면 c(-5.0, -4.8, -4.6, …, 4.6, 4.8, 5.0)라는 수열을 생성하여, 이를 s3라는 이름의 벡터형 객체로 저장하게 됩니다.

> s4 <- seq(length=51, from=-5, by=.2)

아래와 같은 방법으로도 s3와 같은 벡터 s4를 생성할 수 있습니다.

마지막으로 seq() 함수의 다섯번 째 파라미터는 along=vector이며, 다른 파라이터의 입력 없이 이 파라미터만 사용할 경우, 1, 2, …, length(vector)인 수열을 생성 합니다.

A related function is rep() seq()와 비슷한 수열 생성 함수 중, 객체를 반복하는데 사용할 수 있는 rep()라는 함수가 있습니다. 이 함수의 사용법은 아래와 같습니다.

> s5 <- rep(x, times=5)

위 명령어는 x라는 벡터를 처음부터 끝까지 5번 반복해서 나열한 객체를 s5로 지정 합니다.위 함수와 같은 결과를 얻기 위해 아래와 같은 명령문을 사용할 수도 있습니다.

> s6 <- rep(x, each=5)

둘 다 x란 벡터가 가지고 있는 각각의 요소들을 5번씩 반복 나열하여 수열을 생성 합니다.


2.4 논리형 벡터

R은 수치형 벡터 뿐만 아니라 논리값에 대한 연산도 가능합니다.논리형 벡터는 TRUE, FALSE, 그리고 NA (즉 “not available” - 해당 값이 이용가능하지 않아 사용에는 많은 제약이 따름)와 같은 요소로 구성 됩니다.처음 두 개의 요소인 TRUEFALSE가 각각 TF라는 약어로 표기하기도 하며, 이러한 약어 사용은 R에서 초기값으로 지정된 것입니다. 하지만, 사용자가 이 두 문자를 다른 변수나 함수 이름으로 사용할 경우, 더 이상 이러한 초기 약어 지정은 성립하지 않습니다. 따라서, 논리값을 표현할 때에는 TRUEFALSE와 같이 정확하게 표기할 것을 권장 합니다.

논리형 벡터는 조건문 (conditions)에 의해서 생성됩니다.

> temp <- x > 13

예를 들어 아래의 명령문을 입력하면, x 벡터의 각 구성요소에 대해 13 보다 크다는 조건문이 참인지 거짓인지를 판단하여, 해당 구성 요소가 13 보다 큰 위치에는 TRUE, 그렇지 않은 경우에는 FALSE를 출력하여 원래의 x와 같은 길이를 갖는 새 벡터temp를 생성 합니다.

논리 연산자에는 < (작음), <= (작거나 같음), > (큼), >= (크거나 같음), == (같음), 그리고 != (다름) 등이 있습니다. 또한, c1c2와 같이 두 개의 논리 표현식이 있는 경우, c1 & c2는 (“and”)를 나타내는 교집합을 c1 | c2는 (“or”)를 나타내는 합집합을 의미하며, !c1c1를 만족하지 않는 차집합을 의미 합니다.

논리형 벡터들은 일반적인 산술연산에 사용할 수도 있으며, 이 경우 논리값인 FALSE는 숫자 0으로 TRUE는 숫자 1로 변환 되어야 합니다. 이러한 변환을 coerced(강제형변환)이라고 합니다. 그러나 논리형 벡터들이 수치형 벡터로의 강제형변환이 항상 위와 같은 방식으로만 이루어지는 것은 아니며, 여기에 대해서는 다음 섹션에서 살펴보도록 하겠습니다.


2.5 결측값

가끔 벡터의 구성요소들 중 일부가 완전하지 않은 경우가 있습니다.통계적 의미에서 이러한 구성요소 또는 값들은 “not available” (사용이 가능하지 않음) 또는 “missing value”(결측치 혹은 누락된 값)을 의미하며, 이러한 값들은 벡터 내에서 NA라는 특수 문자로 표기 됩니다. 일반적으로 어떤 연산이든 NA에 대한 연산의 결과는 NA가 됩니다.이러한 규칙을 만들게 된 동기는 단순합니다. 이러한 결측치의 연산법을 따로 지정하지 않으면, 결측치의 포함으로 인해 해당 연산이 정의되지 않거나 결과가 출력되지 않기 때문입니다.

함수 is.na(x)x의 각 구성요소 중 NA가 포함되었는지를 확인하여, 논리값인 TRUE또는 FALSE를 갖는 새로운 벡터를 생성 합니다. 따라서, 생성된 벡터의 길이는 원래 벡터인 x와 같아야 하며, 이는 아래의 명령문을 통해 확인해 볼 수 있습니다.

> z <- c(1:3,NA);  ind <- is.na(z)

그러나, NA라는 것은 실제로 단순히 벡터를 구성하는 요소의 값이 사용가능한지에 대한 마커일 뿐 해당 요소에 대한 값이 아니기 때문에 x == NA이라는 논리적 표현식과 is.na(x)는 서로 다른 것을 의미한다는 점을 이해하셔야 합니다. 즉 x == NA는 벡터 x와 길이는 같지만 그 구성요소 모두NA값을 가지므로, 이 식 자체가 논리형 표현식이라 어떤 연산을 수행하기에는 불완전하고 불충분하기 때문입니다.

또한 수치연산의 결과로서 발생하는 또 다른 종류의 결측치(“missing”)인 NaNNot a Number(숫자가 아님)을 의미 합니다. 다음의 두 예제를 통해서 좀 더 자세히 알아 봅시다. values. Examples are

> 0/0

or

> Inf - Inf

위의 두가지 경우 모두 수학적 정의에 따른 계산을 수행할 수 없기 때문에 NaN이라는 결과를 출력하게 됩니다.

요약해보면, is.na(xx)는 구성요소 중 하나 이상이 NA이거나 NaN인 두가지 경우 모두 TRUE 값을 돌려줍니다. 그러나, is.nan(xx)은 오직 구성 요소에 NaN이 포함될 때만 TRUE가 됩니다.

때때로 이렇게 <NA>로 표시된 값들 중, 실제 결측치가 아니라 단지 문자형 벡터가 인용 부호 ("quotes") 없이 사용되었기 때문인 경우도 있으므로 주의하시기 바랍니다.


2.6 문자형 벡터

문자값 또는 문자형 벡터는 종종 R에서 플롯의 라벨 등으로 사용 됩니다. 이러한 문자열은 "x-values" 또는 "New iteration results"과 같이 "" (큰 따옴표)에 의해 구분 됩니다.

문자열의 입력은 큰 따옴표 (")와 작은 따옴표 (')를 모두 사용할 수 있지만, 입력된 문자열을 출력할 때는 큰 따옴표에 의해 각 구성요소가 구분 됩니다. (경우에 따라 큰 따옴표 없이 출력되는 것도 가능 합니다).R에서는 C 언어처럼 \를 확장 문자(escape sequence)로 사용하여 문자열을 처리하는 것이 가능합니다. 따라서, \\를 출력하기 위해서는 ("로 구분된) 문자열 내에 \\을 사용하고, 큰 따옴표 "를 출력하기 위해서는 "를 사용하도록 합니다. 그 밖의 유용한 이스케이프 시퀀스들로는 \n이 있는데 이는 새로운 행(즉, 개행)을, \t는 탭(tab)을, \b는 백스페이스를 나타냅니다. 사용 가능한 확장 문자 대한 전체 목록을 확인하고 싶으시면 ?Quotes을 입력하시길 바랍니다.

c()라는 함수를 이용하면 문자열을 연결하여 새로운 문자열 벡터를 생성할 수 있습니다. 이러한 문자 벡터의 생성은 앞으로 자주 등장하게 될 것입니다.

paste() 함수는 임의의 개수의 인자들을 입력받아, 이들을 한데 묶어 하나의 문자열로 생성 합니다.이 때, 주어진 인자들 중 일부가 숫자라도, 이들 역시 문자형으로 강제형변환이 이루어짐을 아셔야 합니다. 이러한 형변환 결과는 출력을 통해 확일할 수 있는데, 합쳐진 각각의 문자형 인자들 사이는 하나에는 공백문자(white space 또는 blank character)가 포함되어 두 요소가 합쳐졌다는 것을 알 수 있습니다. 이러한 공백문자를 포함한 새로운 문자형 인자의 생성은 sep=string 옵션을 사용하여 다른 문자에 의해 구분되도록 지정하는 것이 가능하며, 아래의 예제처럼 입력시 string은 공백 없이 두 요소를 하나로 합치는 것도 가능합니다.

다음의 예시를 살펴봅니다.

> labs <- paste(c("X","Y"), 1:10, sep="")

위의 할당문은 labs 를 아래와 같은 문자형 벡터로 만들어 줍니다.

c("X1", "Y2", "X3", "Y4", "X5", "Y6", "X7", "Y8", "X9", "Y10")

위 명령문에서 paste()라는 함수는 c("X", "Y")라는 문자형 벡터와 1:10이라는 숫자형 벡터를 하나로 묶어 문자형 벡터를 생성하는데, 두 벡터의 길이가 다르므로 c("X", "Y")가 5번 반복되게 될 것입니다. 또, 구분자가 sep=""로 지정 되었으므로 두 문자 사이에는 아무런 공백이 없을 것입니다. 8


2.7 인덱스 벡터를 사용한 데이터셋의 선택과 수정

벡터의 이름 바로 뒤에 대괄호([])와 함께 사용된 index vector(인덱스 벡터)를 통해 벡터의 일부 구성 요소만 선택하는 것이 가능합니다. 여기서 인덱스 벡터란 대괄호 내부에 쓰인 벡터를 의미 합니다.좀 더 일반적으로 말하면, 연산의 결과로 벡터를 생성하게 되는 어떠한 표현식이라도 표현식 바로 다음에 대괄호와 함께 인덱스 벡터를 사용해서 벡터 구성요소 중 일부만 선택하는 것이 가능합니다.

이러한 인덱스 벡터에는 다음과 같은 네가지 유형이 있습니다.

  1. 논리형 인덱스 벡터: 이 경우는 인덱스 벡터는 반드시 선택할 구성요소를 포함한 벡터와 길이가 같아야 합니다. 인덱스 벡터에서 TRUE에 대응하는 요소들만 선택되고, FALSE에 대응하는 요소들은 제거될 것입니다. 예를 들면,
    > y <- x[!is.na(x)]
    

    위의 명령문은 x 벡터 중 결측치가 아닌 요소들만을 원래의 순서대로 포함하는 객체 y를 생성합니다. 만약 x에 결측치가 포함되어 있다면 새로 생성된 y의 길이는 x 보다 짧을 것입니다. 또 한,

    > (x+1)[(!is.na(x)) & x>0] -> z
    

    위의 명령어는 x의 구성요소들 중 결측치가 아니면서 양수인 요소들만을 찾아서 이들에 각각 1을 더하여 객체 z를 생성합니다.

  2. 양의 정수 인덱스 벡터: 이 경우의 인덱스 벡터는 반드시 {1, 2, …, length(x)} 범위 내에 있어야 합니다. 선택된 구성요소들은 인덱스 벡터에서 지정한 순서 대로 선택되어 하나로 묶여지게 됩니다. 선택된 결과는 사용된 인덱스 벡터의 길이와 같으며, 인덱스 벡터의 길이는 임의로 선택 가능합니다. 예를 들어, x[6]x의 여섯번째 구성요소를 선택하며,
    > x[1:10]
    

    위의 명령문은 (x의 길이가 10보다 작지만 않다면,) x가 가진 구성요소 중 처음 10개의 요소들을 선택 합니다. 또,

    > c("x","y")[rep(c(1,2,2,1), times=4)]
    

    위의 명령문은 (물론 이렇게 어렵게 사용하는 경우는 거의 없지만) "x", "y", "y", "x"가 4번씩 반복되어 구성된 전체 길이 16인 문자형 벡터를 생성 합니다.

  3. 음의 정수 인덱스 벡터: 이 경우, 인덱스 벡터는 선택된 요소들을 포함하는 것이 아니라 제외할 목적으로 사용됩니다. 따라서,
    > y <- x[-(1:5)]
    

    위의 명령문은 x의 처음 5개의 구성요소들만 제외시켜 y를 생성 합니다.

  4. 문자형 인덱스 벡터: 이 경우는 객체의 각 구성요소들이 names라는 속성(i.e.객체 안의 각 구성요소(변수)의 이름)을 가지고 있을 때에만 인덱스 벡터의 이용이 가능합니다. 이때, names를 한 데 묶어 나열한 벡터를 네임벡터 (names vector)라고하며, 위에서 설명한 양의 정수 인덱스 벡터와 동일한 방식으로 사용하면 됩니다.다음의 예제를 보면, 우선 fruit이라는 수치형 벡터에 names() 라는 함수를 이용하여 각각의 구성요소에 "orange", "banana", "apple", "peach"라는 names 속성을 부여합니다.이제, 만약 fruit 벡터의 세번째와 첫번째 요소를 선택하고 싶다면, [c("apple","orange")]를 사용하면 됩니다.
    > fruit <- c(5, 10, 1, 20)
    > names(fruit) <- c("orange", "banana", "apple", "peach")
    > lunch <- fruit[c("apple","orange")]
    

    이렇게 영문과 숫자의 조합(alphanumeric)인 names를 이용할 경우 수치형 인덱스를 이용하여 구성요소를 선택할 때 보다 기억하기에 편리하다는 장점이 있습니다. 이 옵션은 특히 나중에 설명하게 될 데이터 프레임과 연관이 있습니다.

인덱스를 사용한 표현식은 벡터의 일부 구성요소에 새로운 값을 할당하기 위한 목적으로도 사용 되는데,이 경우 주로 인덱스 벡터를 적용한 벡터 그 자신이 할당의 대상이 됩니다. 여기서 표현식은 반드시vector[index_vector]의 형태로 사용되야 하며, 네임벡터의 위치에 어떠한 표현식이든 자유롭게 사용될 수 있는 것은 아닙니다. 예제를 통해 살펴보면, 다음과 같은 명령문을 사용하면 x에서 결측값이 있는 위치를 확인하여 이 위치의 결측값에 0을 할당 하는 것이 가능합니다.

다음의 예시를 살펴봅니다.

> x[is.na(x)] <- 0

또 다음의 예제에서는 y의 값들 중 0 보다 작은 값들을 찾고 이들의 부호를 바꿔줍니다.

> y[y < 0] <- -y[y < 0]

결과적으로 위의 예제는 아래의 명령문을 수행한 것과 같은 결과를 얻습니다.

> y <- abs(y)

2.8 객체의 다른 유형들

벡터는 R에서 가장 중요한 객체입니다. 하지만 이번 섹션에서는 다른 유형의 객체들에 대해 간단히 소개하도록 하겠습니다.


3 객체의 저장방식과 속성


3.1 고유속성: 저장방법 그리고 길이

R에서 정보처리 (연산 및 수행)의 기본단위는 전문용어로 objects(객체)라고 부르는 요소들입니다.이러한 객체의 종류에는 (실수) 수치형 및 복소수형, 논리형 그리고 문자형 벡터등이 있습니다.이러한 벡터의 구조를 “atomic” 이라고 하는데, 그 이유는 이들 벡터의 구성요소는 반드시 numeric 9, complex, logical, character, 그리고 raw 중 하나의 타입 혹은 mode(모드)로만 되어있기 때문입니다.

벡터는 반드시 같은 모드에서 나온 값들로만 이루어져야 합니다.따라서 어떠한 벡터라도 반드시 logical(논리형), numeric(수치형), complex(복소수형), character(문자형) 또는 raw 중의 하나의 모드이어야 합니다.(이 규칙에 대한 유일하고 명백한 예외가 있다면 그것은 NA로 표기되는 결측값일 것 입니다.하지만, 사실 여러 이유로 NA 값이 생성 됩니다).벡터는 empty(아무런 구성요소 없이 비어 있는) 상태라고 하더라도 모드를 가질 수 있습니다. 예를들어, 비어있는 문자열 벡터 character(0)나, 비어있는 수치형 벡터 numeric(0) 등이 있습니다.

R은 또한 list(리스트)라는 모드를 가진 lists(리스트) 객체들을 대상으로 연산을 수행할 수 있습니다. 리스트에는 동일하지 않은 모드를 가진 여러 객체들을 일정한 순서대로 나열할 수 있습니다. lists(리스트)는 또한 atomic structure (가장 단순한 기본구조)이기 보다는 “recursive”(재귀)구조를 가지는데, 그 이유는 리스트의 구성요소 그 자체가 리스트 안에 포함될 수 있기 때문입니다.

또 다른 재귀구조는 모드가 function(함수) 또는 expression(표현식)인 경우 입니다.함수는 나중에 설명하게 될 사용자 정의 함수와 함께 R 시스템의 일부를 구성하는 객체입니다.표현식은 R에서 모델링에 사용되는 formulae(공식)을 언급할 때 간접적으로 등장하는 것을 제외하고는 이 문서에서는 다루지 않을 것이지만, 이 역시 R시스템의 고급 활용을 위해 필요한 객체 입니다.

한 객체의 mode(모드)를 확인하여, 우리는 이 객체를 구성하는 요소들의 기본형(basic type)을 알 수 있습니다. 모드는 한 객체의 속성 (property) 중 특별한 하나의 예 입니다. 모든 객체가 갖는 또 다른 속성에 length(길이)가 있습니다.명령문 mode(object)mode(object)를 사용하여 객체의 모드와 길이를 알 수 있습니다. 10

객체에 대한 더 많은 속성들은 attributes(object)를 사용해서 볼 수 있으며, 궁금한 점은 Getting and setting attributes (속성을 설정하고 확인하기)를 참고하시길 바랍니다.이러한 이유로, mode(모드)와 length(길이)는 객체의 “intrinsic attributes”(본질적 속성)이라고 합니다.

예를 들어, 만약 z가 길이 100인 복소수형 벡터라고 한다면, 표현식 mode(z)는 문자열 "complex"(복소수)을 출력하고, length(z)100을 출력 합니다.

R에서는 어디든 필요한 곳에서 모드를 변경할 수 있습니다. 예제를 통해 살펴보면,

> z <- 0:9

위에서 생성한 0 부터 9까지의 숫자로 이루어진 수열 zc("0", "1", "2", …, "9")의 값을 갖는 문자형 벡터 digits으로 전환될 수 있습니다.

> digits <- as.character(z)

이 문자형 벡터는 다음과 같은 방법으로 수치형 벡터로 coercion(강제형변환) 또는 모드 변환할 수 있습니다:

> d <- as.integer(digits)

이제 dz는 동일한 벡터 입니다.11 이와 같이 객체의 모드를 변경하거나, 한 객체가 현재 지정된 모드 이외의 다른 속성을 가질 수 있는지 확인하기 위해 as.something 형태의 다양한 함수 모음을 이용할 수 있습니다.이러한 함수들을 능숙하게 사용하기 위해서는 다양한 도움말이 필요할 것 입니다.


3.2 객체의 길이 변경

An “empty” object may still have a mode. For example

> e <- numeric()

위의 명령문은 수치형 모드를 갖는 비어있는 벡터 e를 생성합니다.마찬가지로, character()은 비어있는 문자형 벡터를 생성합니다.일단 임의의 크기를 갖는 객체가 생성하고 나면,이전 범위 밖에 인덱스 값을 지정하는 것으로 새 구성요소를 간단히 추가할 수 있습니다.

> e[3] <- 17

위의 명령문으로 길이가 3인 벡터 e가 생성 됩니다. (별도 지정이 없었으므로, 처음 두 개의 구성요소들은 NA가 될 것입니다.) 이런 방식으로 구성요소를 추가하는 것은 새로 추가되는 구성요소가 이미 존재하는 구성요소들과 모드만 일치한다면, 어떤 구조의 객체라도 모두 적용 가능합니다.

때로는, 데이터를 입력할 때 사용하는 scan() 함수처럼, 자동적으로 객체의 길이가 조정될 때가 있습니다.

반대로, 객체의 크기를 직접 조정하고 싶다면, 그렇게 하기 위한 할당문을 사용하면 됩니다.예를들어, 길이가 10인 alpha라는 객체가 있다면,아래의 할당문은 길이가 5이고, 이전 alpha의 구성성분 중 짝수번 째에 해당하는 요소들만을 선택하여 새로운 객체인 alpha를 생성합니다. (이전 인덱스는 더 이상 남아있지 않습니다.)

> alpha <- alpha[2 * 1:5]

이 중 처음 세 개의 구성요소만을 포함하는 alpha를 생성하고자하면, 다음 문장과 같이 하면 됩니다.

> length(alpha) <- 3

비슷한 방법으로 벡터의 길이를 늘리는 것도 가능합니다. (늘어난 길이만큼 결측값으로 채워지겠지만요.)


3.3 Getting and setting attributes (속성을 설정하고 확인하기)

함수 attributes(object)는 해당 객체에 현재 지정되어 있는 모든 (내재형이 아닌,non-intrinsic) 속성들을 리스트로 나열해 줍니다. 또 함수 attr(object, name)는 객체의 좀 더 구체적인 속성을 선택하는데 사용 됩니다. 그러나, 이러한 함수들은, R 객체에 작성날짜나 특별한 연산자를 연결시킬 때와 같은 아주 특별한 경우를 제외하고는 거의 사용되지 않습니다. 하지만, 이와 관련된 개념을 알아두는 것은 매우 중요합니다.

객체에 속성을 새로 추가하거나 삭제할 때는 특별히 주의를 기울이시길 바랍니다. 이런 속성 변경의 대상이 되는 객체들이 R에서 사용되는 객체 시스템의 매우 중요한 부분이기 때문입니다.

할당문의 좌측에 함수 object를 사용하면, 새로운 속성을 할당하거나 존재하는 속성을 변경할 수 있습니다. 아래와 같이 입력하면, R은 벡터 z를 마치 크기가 10행 10열인 행렬처럼 다룰 수 있게 됩니다.

> attr(z, "dim") <- c(10,10)

allows R to treat z as if it were a 10-by-10 matrix.


3.4 객체의 클래스

R에 존재하는 모든 객체들은 class(클래스)라는 것을 갖습니다.이 클래스의 종류는 함수 class를 사용해서 확인할 수 있습니다.간단한 벡터의 경우, 클래스는 "numeric", "logical", "character" 또는 "list"와 같이 단순히 벡터의 모드를 의미 합니다.그러나, "matrix", "array", "factor" 그리고 "data.frame"는 클래스로 다른 값을 가질 수 있습니다.

객체의 class(클래스)가 가진 특별한 속성 중 하나는 R의 object-oriented style (객체지향스타일) 12 프로그래밍을 가능하게 한다는 점입니다.예를 들어, 만약 객체가 "data.frame"을 그 클래스로 가진다면,이 객체를 출력은 정해진 특정한 방식대로 이루어집니다. 이 객체에 plot() 함수를 적용할 경우, 이미 정해진 그래픽의 형태로 시각화하게 되고, 또 summary()와 같이 일반(generic)함수를 사용할 경우, 객체가 가지고 있는 클래스를 인자의 형태로 받아, 클래스에 따른 정의대로 결과물을 출력합니다.

클래스 효과를 일시적으로 제거하기 위해서는 unclass()라는 함수를 사용하면 됩니다. 예를들어 만약 winter라는 객체가 클래스 "data.frame"(데이터 프레임)을 가지고 있다면, 아래의 명령문을 실행하면 행렬이라기 보다는 데이터 프레임의 형식을 갖추어 데이터를 출력하게 됩니다.

> winter

반면에 아래의 명령문을 실행해서 클래스 효과를 지우면 일반적인 리스트의 형식으로 출력됩니다.

> unclass(winter)

이러한 클래스의 활용은 매우 특별한 경우에 한해서만 필요하므로, 여기서는 단순히 클래스와 일반함수의 기본 개념에만 익숙해지면 됩니다.

일반함수와 클래스에 대해서는 Object orientation (객체지향적 방법) 부분에서 더 자세히 다루겠지만, 여기에서는 이쯤에서 간단히 마치겠습니다.


4 순서형과 비순서형 요인

factor(요인)은 같은 길이를 가진 다른 벡터의 다른 구성요소들을 이산형으로 구분(Classification) 또는 그룹핑(grouping)된 것을 표현해주는 벡터형 객체입니다.R에서는 ordered(순서형)과 unordered(비순서형) 요인을 모두 사용 가능합니다.요인의 활용이 정말 필요한 것은 see Contrasts 부분에서 설명할 model formulae(모형 공식)을 사용할 때이지만, 여기에서는 좀 더 간단한 예제를 우선 다루겠습니다.

4.1 구체적인 예제

예를들어, Australia(오스트레일리아, 호주)의 모든 지역(호주에는 Australian Capital Territory, New South Wales, the Northern Territory, Queensland, South Australia, Tasmania, Victoria and Western Australia 라는 총 8개의 행정 구역이 있습니다)으로부터 온 30명의 회계사 샘플과 그들의 출신 지역에 대한 정보가 문자형 벡터인 state에 약자로 다음과 같이 기록되어있습니다.

> state <- c("tas", "sa",  "qld", "nsw", "nsw", "nt",  "wa",  "wa",
             "qld", "vic", "nsw", "vic", "qld", "qld", "sa",  "tas",
             "sa",  "nt",  "wa",  "vic", "qld", "nsw", "nsw", "wa",
             "sa",  "act", "nsw", "vic", "vic", "act")

문자형 벡터의 경우에는 “sorted”(정렬)이라는 것은 알파벳순서로 나열된 것을 의미합니다.

여기에 대한 factor(요인)은 factor() 함수를 이용하여 아래와 같이 생성합니다:

> statef <- factor(state)

print() 함수를 사용해서 요인을 출력할 경우, 다른 객체들과는 다소 다른 방식으로 출력됩니다:

> statef
 [1] tas sa  qld nsw nsw nt  wa  wa  qld vic nsw vic qld qld sa
[16] tas sa  nt  wa  vic qld nsw nsw wa  sa  act nsw vic vic act
Levels:  act nsw nt qld sa tas vic wa

요인의 수준(levels)을 확인하기 위해서는 함수 levels()를 사용하면 됩니다.

> levels(statef)
[1] "act" "nsw" "nt"  "qld" "sa"  "tas" "vic" "wa"

4.2 함수 tapply()와 비정형 배열

앞부분에서 사용된 예제를 계속해서, 이제 30명의 회계사의 수입(income)에 대한 정보가 아래와 같이 벡터로 (적당한 화폐단위로 기록되어) 제공되었다고 가정합시다.

> incomes <- c(60, 49, 40, 61, 64, 60, 59, 54, 62, 69, 70, 42, 56,
               61, 61, 61, 58, 51, 48, 65, 49, 49, 41, 48, 52, 46,
               59, 46, 58, 43)

각 주(state) 별 평균소득을 계산하고 싶다면 아래와 같이 tapply() 함수를 사용하면 됩니다.

> incmeans <- tapply(incomes, statef, mean)

위 명령어를 실행하면 아래와 같이 (state의) 각 수준(levels)에 해당하는 평균이 벡터로 출력 됩니다.

   act    nsw     nt    qld     sa    tas    vic     wa
44.500 57.333 55.500 53.600 55.000 60.500 56.000 52.250

함수 tapply()를 사용하면 이 함수의 첫번째 인자인 incomes에 대해, 이 함수의 두번째 인자인 statef에 정의된 요인의 수준별로, 세번째 인자인 함수 mean()을 계산합니다. 마치 각각의 두번째 요인의 수준별로 별개의 벡터가 존재하는 것 처럼 말이지요. 13따라서, 결과로 생성된 벡터의 길이는 반드시 요인 수준의 개수와 같아야 합니다.이러한 연산에 대해 더 자세히 알고 싶은 분은 도움말을 참고하시길 바랍니다.

어쩌면 여러분은 이 예제에서 평균소득에 대한 표준오차(standard error)를 계산해보고 싶을 수도 있을 것 입니다.이를 위해, 아래와 같이 주어진 벡터의 표준오차를 계산하는 R 함수를 작성할 수 있습니다.var()라는 샘플 분산을 계산하는 빌트인(built-in) 함수가 존재하기 때문에, 이 함수는 아래와 같이 간단한 한줄짜리 함수로 표현 가능합니다:

> stderr <- function(x) sqrt(var(x)/length(x))

(함수를 작성하는 방법에 대해서는 추후에 Writing your own functions (사용자 정의함수 작성하기) 편에서 다룰 것입니다. 또 위의 함수작성 예제는 실제로는 별로 의미는 없는데, R에는 이미 sd()라는 표준오차 계산 함수가 포함되어 있기 때문입니다). 위의 함수에 할당을 하면, 아래와 같이 표준오차가 계산되며,

> incster <- tapply(incomes, statef, stderr)

그 결과는 다음과 같습니다.

> incster
act    nsw  nt    qld     sa tas   vic     wa
1.5 4.3102 4.5 4.1061 2.7386 0.5 5.244 2.6575

연습삼아 state 별 평균소득에 대한 95% 신뢰구간을 구해보고 싶은 분도 있을 것입니다.이를 위해서는, tapply() 함수와 함께 length(), qt()와 같은 함수들을 사용해야 할 것이라 생각되는데, length()는 샘플 크기를, qt()는 t-분포에서 95% 에 해당하는 분위수를 찾아주는 함수 입니다.(참고로 R에 포함된 t-테스트 관련 함수들을 이용하는 것도 가능할 것입니다).

위의 예제에서 살펴 본 tapply() 함수에 여러 개의 범주를 표시하기 위해 좀 더 복잡하게 표현된 인덱스 벡터를 사용하는 것도 가능합니다. 예를들어, 위 예제에서 state 와 성별이라는 두 가지 요인을 동시에 고려하여 회계사의 수입을 보고 싶다고 가정합시다.이 경우, (한 개의 요인을 고려할 때 처럼) 다음과 같은 식으로 연산이 처리 됩니다.우선, 벡터의 구성요소들이 요인의 수준 별로 그룹화 됩니다. 그리고 이 그룹화된 벡터 구성요소 별로 함수가 각각 적용 됩니다. 즉, 각 요인 수준별로 계산된 결과값에, 해당 요인의 levels 속성을 각각 레이블링 하는 것 입니다.

하나의 벡터와 하나의 레이블링 요인을 조합하는 것은 ragged array(비정형 배열)의 하나의 예시로 볼 수 있는데,그것은 그룹화 된 부분의 크기가 서로 다른 경우가 대부분이기 때문입니다.만약 그룹화 된 각 부분의 크기가 모두 같다면, 다음 섹션에서 살펴보게 될 방법을 사용하여 훨씬 효율적으로 연산을 수행할 수 있습니다.


4.3 순서형 요인

요인(factor)의 수준(levels)들은 기본적으로 알파벳 순서로 저장되지만, factor 함수를 이용하면 사용자가 별도의 순서를 지정하는 것도 가능합니다.

어떤 경우에는 수준들이 우리가 원하는대로 이미 지정되어 있거나, 통계분석 시 필요한 형태로 되어있는 경우도 있습니다. ordered() 함수는 요인을 순서형으로 생성한다는 점을 빼면 factor와 다르지 않습니다.대부분의 경우, 순서형과 비순서형 요인의 차이는 순서형 요인만 수준을 일정한 순서대로 출력하는 점 뿐이지만, 선형 모형 적합에서 요인을 이용하여 contrasts(대조)를 생성할 경우, 서로 다른 순서가 다른 결과물을 산출하게 된다는 점을 기억하시기 바랍니다.


5 Arrays and matrices (배열과 행렬)


5.1 배열

배열(array)이라는 것은 쉽게 말해 다차원상에 데이터가 저장될 수 있도록 데이터 엔트리(data entry, 데이터가 위치하는 하나하나를 공간 또는 한개의 데이터을 의미함)를 구조화한 것 입니다. 다차원이라는 것은 우리 머릿속에 개념상으로 존재하지만, 데이터를 일렬로 벡터와 같은 형태로 읽어들이는 컴퓨터에는 다차원의 개념이 없습니다.그래서 데이터에 다차원 구조를 주기 위해서는 이 배열이라는 개념을 이용 해야하며, R은 행렬과 같이 일정한 형태로 된 배열을 생성하고 조작할 수 있는 간편한 기능들을 제공합니다.

이러한 다차원 구조의 실제적인 구현을 위해서는 차원벡터 (dimension vector)라는 것을 활용하게 되는데, 이는 음의 값이 아닌 정수(non-negative) 벡터로 되어 있습니다. 차원벡터의 길이가 k인 경우, 데이터는 k-차원의 배열이 됩니다. 좀 더 구체적으로, 하나의 행렬은 2-차원 배열의 예라고 볼 수 있습니다. 각 차원(즉, 차원벡터의 구성요소)은 양의 정수를 인덱스 값으로 갖습니다.

R에서 배열로 사용되기 위해서는 해당 벡터의 dim 속성(attribute)으로 차원벡터가 지정되어 있어야만 합니다.이해를 돕기 위해서 아래의 예제를 살펴보도록 합니다. z는 1500개의 구성요소를 갖는 벡터라고 가정합시다.

> dim(z) <- c(3,5,100)

다음의 할당문을 실행하면, 이 벡터는 3-차원 구조의, 3 by 5 by 100 크기의 배열로 지정 됩니다. 여기서 첫번째 차원은 3개의 구성요소를 가지므로, 1, 2, 3 세 개의 인덱스에 의해 표현되며, 마찬가지로 두번째 차원은 5개의 인덱스를, 마지막으로 세번째 차원은 100개의 인덱스를 갖습니다. 즉, 차원벡터의 각 구성요소는 각 차원이 갖는 인덱스의 길이를 의미합니다.

이렇게 dim이라는 속성을 이용하는 방법 외에도 matrix()array()와 같은 함수를 사용하면 array() 함수편의 예제들처럼 좀 더 간단하고 쉽게 배열을 지정할 수 있습니다.

배열을 구성하는 데이터 벡터의 구성요소의 값들은 FORTRAN 프로그램에서처럼 “column major order” 방법에 의해 나열 됩니다. 이 방법은 차원벡터의 첫번째 인덱스부터 순서대로 배열되기 시작해서 마지막 인덱스가 가장 나중에 사용되는 배열되는 방식 입니다.

좀 더 구체적인 예를 들면, a라는 배열의 차원벡터가 c(3,4,2)이라고 가정합시다.이 배열 a에는 총 3 * 4 * 2 = 24 개의 데이터 엔트리가 포함되어 있고, 이 데이터 벡터는 a[1,1,1], a[2,1,1], …, a[2,4,2], a[3,4,2]의 순서로 엔트리들을 배열 안에 나열하고 있습니다.

1차원일 배열의 경우 (출력을 포함하여) 거의 벡터와 같은 방식으로 처리됩니다만, 몇 가지 예외가 있어서 사용에 주의가 필요합니다.


5.2 배열 인덱싱(array indexing)과 구성요소의 선택적 지정(subsections)

배열의 각 구성요소들은 배열 이름 바로 뒤에 대괄호([])사이에 컴마로 구분된 첨자(subscript)를 사용하여 선택할 수 있습니다. 이러한 선택을 좀 더 일반화하면, 한 배열의 첨자를 사용할 위치에 index vectors(인덱스 벡터)의 시퀀스를 사용하면 해당 배열의 어떤 부분이라도 선택할 수 있습니다; 하지만 인덱스 벡터의 구성요소가 아무것도 선택되지 않으면 (즉, empty 상태), 해당 첨자가 가질 수 있는 모든 값이 범위로 선택 됩니다.

More generally, subsections of an array may be specified by giving a sequence of index vectors in place of subscripts; however if any index position is given an empty index vector, then the full range of that subscript is taken.

이해를 돕기 위해 앞의 예제의 a라는 벡터를 다시 사용하면, a[2,,]c(4,2)의 차원벡터를 갖는 4 * 2 배열이며, 순서대로 다음의 값들을 포함하는 데이터 벡터이기도 합니다.이것은 원래 배열 a의 차원이 선택되기 때문입니다. 따라서 차원벡터의 길이에 맞추어 42열을 가진 행렬처럼 출력된 것 입니다.

c(a[2,1,1], a[2,2,1], a[2,3,1], a[2,4,1],
  a[2,1,2], a[2,2,2], a[2,3,2], a[2,4,2])

a[,,]는 배열 a 그 자체를 의미하는데, 이것은 첨자를 전혀 사용하지 않고 그냥 a만 사용한 것과 같습니다.

어떤 배열이 주어지면, 예를 들어 Z라는 배열이 있다면, 이 배열의 차원벡터는 함수 dim(Z)를 사용하여 확인 가능합니다.

또, 만약 배열의 이름 뒤에 a[3] 또는 a[3:10]과 같이 오직 한개의 첨자 또는 인덱스 벡터가 사용되면, 이 첨자와 인덱스에 해당하는 데이터 엔트리로만 구성된 벡터가 선택 됩니다: 따라서, 이 경우에는 차원벡터가 무시됩니다. 하지만, 인덱스가 벡터가 아니라 배열로 지정될 수도 있으며, 여기에 대해서는 다음 부분에서 다루겠습니다.


5.3 Index matrices (인덱스 행렬)

배열의 첨자가 오는 위치에 인덱스 벡터 뿐 아니라, 행렬 형태인 index matrix(인덱스 행렬)을 사용할 수 있으며, 배열 내 (같은 행이나 열이 아니라)여러 위치에 흩어져 있는 여러 개의 구성 요소들에 하나의 벡터 안에 든 여러 개의 새로운 값들을 동시에 입력하거나, 배열 내 여러 위치의 구성요소들을 하나의 벡터로 읽어내기 위해 사용합니다.

다음의 행렬을 사용한 예제를 통해 좀 더 자세히 설명하겠습니다. 이중(doubly) 인덱스를 사용하는 배열의 경우, 이 배열의 인덱스 행렬을 2개의 열과 필요한 만큼(데이터의 길이)의 행으로 구성됩니다. 이 인덱스 행렬의 엔트리들은 이중 인덱스 된 배열의 행과 열의 인덱스에 해당합니다. 예를 들어, 크기가 45열인 배열 X가 있다고 가정하고, X에 대해서 다음의 연산을 수행한다고 합시다:

위의 작업을 수행하기 위해서는 아래 예제와 같이 첨자의 위치에 사용될 32 열의 첨자 배열이 필요합니다.

> x <- array(1:20, dim=c(4,5))   # Generate a 4 by 5 array.
> x
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    5    9   13   17
[2,]    2    6   10   14   18
[3,]    3    7   11   15   19
[4,]    4    8   12   16   20
> i <- array(c(1:3,3:1), dim=c(3,2))
> i                             # i is a 3 by 2 index array.
     [,1] [,2]
[1,]    1    3
[2,]    2    2
[3,]    3    1
> x[i]                          # Extract those elements
[1] 9 6 3
> x[i] <- 0                     # Replace those elements by zeros.
> x
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    5    0   13   17
[2,]    2    0   10   14   18
[3,]    0    7   11   15   19
[4,]    4    8   12   16   20
>

인덱스 행렬의 구성요소는 음의 값을 가질 수 없으나, NA0은 사용할 수 있습니다.만약, 인덱스 행렬에 0을 포함한 행이 있다면, 해당 행은 무시될 것입니다. 이와 유사하게, NA를 포함하는 행이 있다면, 해당 행은 모두 NA로 출력될 것 입니다.

중요한 예제는 아니지만, b 개의 수준을 가진 blocks이라는 요인과 v 개의 수준을 가지고 있는 varieties 변수로 정의되는 블록 디자인(block design)에 사용될 (비환원) 디자인 매트릭스(design matrix)를 생성한다고 가정합시다. 더 나아가, 이 실험은 n개의 구획(plot)을 포함한고 가정합시다. 이 실험의 디자인 매트릭스는 아래와 같이 생성합니다:

> Xb <- matrix(0, n, b)
> Xv <- matrix(0, n, v)
> ib <- cbind(1:n, blocks)
> iv <- cbind(1:n, varieties)
> Xb[ib] <- 1
> Xv[iv] <- 1
> X <- cbind(Xb, Xv)

만약 N이라는 인시던스 행렬(incidence matrix)를 생성하고자 한다면, 아래와 같이 할 수 있습니다.

> N <- crossprod(Xb, Xv)

그러나, 다음과 같이 table()함수를 이용하면 좀 더 쉽게 위에서 얻은 것과 동일한 행렬을 얻을 수 있습니다.

> N <- table(blocks, varieties)

인덱스 행렬은 반드시 수치형으로 구성되어야 합니다: 만약, 논리형이나 문자형 같이 다른 형식으로 된 행렬이 입력되면 인덱스 벡터로 간주 됩니다.


5.4 array() 함수

배열은 벡터에 dim이라는 속성을 부여하여 생성하는 방법 외에도, 아래와 같이 array 함수를 이용하여 생성할 수도 있습니다.

> Z <- array(data_vector, dim_vector)

예를 들어, 벡터 h가 24개 또는 그 보다 적은 수의 숫자로 구성되어 있다면, 아래 명령문은 34 열로 구성된 2개의 3차원 배열을 Z로 지정합니다.

> Z <- array(h, dim=c(3,4,2))

특히 h가 정확히 24개의 구성요소를 가지고 있다면, 위 명령문의 실행 결과는 아래 명령문의 실행 결과와 같습니다.

> Z <- h ; dim(Z) <- c(3,4,2)

하지만, 벡터 h가 24 개 보다 적은 수의 구성요소를 가지면, array 함수 사용시 24로 지정된 배열의 크기를 맞추기위해 벡터 h의 첫번째 원소부터 재사용하게 됩니다.이런 재활용 규칙(recycling rule)에 대해서는 see The recycling rule를 살펴보시길 바랍니다.그러나, dim(h) <- c(3,4,2)와 같이 dim 속성을 변경하고자 할 때는 지정된 길이가 다르기 때문에 에러 메세지가 나타날 것 입니다.아래는 다소 극단적이긴 하지만, 흔히 볼 수 있는 예제 입니다.

> Z <- array(0, c(3,4,2))

makes Z an array of all zeros.

여기에서 dim(Z)은 차원벡터 c(3,4,2)를 의미하며, Z[1:24]는 벡터 h와 동일한 데이터 벡터를 의미 합니다. 또, Z[]와 같이 아무런 첨자를 갖지 않는 경우나 단순히 Z라고 배열 이름만 사용하는 것은 Z의 모든 구성요소로 이루어진 배열 그 자체를 의미 합니다.

배열에 산술연산을 적용하면 기본적으로 배열을 구성하는 데이터 벡터안에 든 원소 단위별로 연산이 이루어집니다.이때 연산에 사용되는 각 배열(피연산자, operand)의 dim 속성이 모두 일치해야만, 원래와 동일한 차원벡터를 가진 결과물을 얻을 수 있습니다.따라서 만약 A, B, C가 모든 같은 dim 속성을 가진 배열이면, 아래와 같이 데이터 벡터의 원소 단위별로 연산을 수행한 결과가 같은 차원벡터를 가진 배열 D로 저장 됩니다.

> D <- 2*A*B + C + 1

하지만 배열과 벡터를 함께 사용하는 연산을 정확히 사용하기 위해서는 좀 더 주의해야할 부분이 많습니다.


5.4.1 벡터와 배열을 함께 이용하여 연산하는 방법 그리고 재활용 규칙

벡터와 배열을 동시에 사용해서 원소 단위별로 연산을 수행할 때 적용되는 정확한 규칙을 설명하는 것은 꽤 까다롭고 어려운 편 입니다. 하지만 지금까지의 경험을 바탕으로 한 다음의 내용은 꽤 쓸만한 길잡이가 될 것 입니다.


5.5 두 배열의 외적

배열에 적용되는 연산 중 중요한 것 중 하나는 %o%로 정의된 연산자를 사용하는 외적 (outer product)일 것 입니다. 예를 들어, ab이라는 두개의 수치형 배열이 존재할 경우, 이 두 배열에 외적(outer product)은 이 두 배열의 차원을 모두 포함한 c(dim(a), dim(b))를 차원 벡터로 갖고, 배열 a의 구성요소와 배열 b의 구성요소의 모든 가능한 조합을 곱한 값을 데이터 벡터로 갖는 배열 입니다.

> ab <- a %o% b

다음은 또 다른 방법입니다.

> ab <- outer(a, b, "*")

이 외적(outer product)에서의 곱하기 연산은 두 개의 변수를 대상으로 수행하는 다른 어떤 함수로도 대체 가능합니다.예를 들어, R에서 두 개의 벡터 x- 와 y- 를 각각의 축으로 정의한 좌표 평면상 존재하는 모든 점들에 대해 f(x; y) = cos(y)/(1 + x^2)과 같은 함수를 적용하는 방법은 다음과 같습니다.

> f <- function(x, y) cos(y)/(1 + x^2)
> z <- outer(x, y, f)

두 개의 벡터를 사용해서 외적을 할 때 주의할 점은, 결과물이 이중 첨자(doubly subscriped) 배열이라는 점입니다. (이것은 행렬이기도 합니다.) 외적 연산에 대해서는 교환법칙이 성립하지 않는다(non-commutative)는 점을 주의하시기 바랍니다. 사용자 정의 R 함수를 만드는 법에 대해서는 Writing your own functions (사용자 정의함수 작성하기)에서 더 다루게 될 것입니다.

예제: 2행 2열인 행렬의 행렬식 (determinant) 계산하기

다소 작위적이긴 하지만, 이해하기 쉬운 예를 하나 들어봅시다.먼저, [a, b; c, d]의 형태를 갖는 22 열의 행렬을 가정하고, 이 행렬의 각 구성요소는 음수가 아닌 (nonegative) 0, 1, …, 9 범위의 한자리의 정수값이라고 합시다.

여기서 우리의 과제는 모든 존재 가능한 행렬들에 대해 ad - bc으로 계산되는 행렬식(determinant)을 계산해서, 행렬식이 갖는 모든 값의 빈도를 하이 확률 빈도 (high density) 플롯으로 그리는 것입니다. 여기서 만약 각 정수들(행렬의 구성요소)의 선택은 균등한 확률(uniformly at random)로 독립적(independently)으로 이루어졌다고 가정하면, 이 작업은 행렬식(determinant)의 확률 분포를 찾는 것이 됩니다.

이 복잡한 과제를 간단히 수행하는 방법 중 하나는 아래와 같이 outer() 함수를 두번 사용하는 것 입니다:

> d <- outer(0:9, 0:9)
> fr <- table(outer(d, d, "-"))
> plot(as.numeric(names(fr)), fr, type="h",
       xlab="Determinant", ylab="Frequency")

여기서 행렬식이 갖는 모든 값의 도수분포표인 frnames 속성이 행렬식이 갖는 값들의 범위를 나타내기 위해 수치형으로 강제형변환 되었다는 점을 주의깊게 살펴보시기 바랍니다. 이러한 수치로의 전환하는 가장 "쉬운" 방법은 아마도 Loops and conditional execution (반복 및 조건부 실행) 편에서 다루게 될for라는 반복문을 이용하는 것인데, 이 방법은 매우 비효율적이라 실용적이지 못합니다.

아마도 전환하게 될 행렬이 20개 중의 하나 꼴로 특이(singular)행렬이라는 점 역시 놀라울 것 같네요.


5.6 배열의 전치에 사용되는 일반화된 방법

함수 aperm(a, perm) 배열 a를 차원 별로 순서를 재배치하는 (permutating)하는 함수 입니다. perm 입력 인자(argument,함수의 parameter와 거의 비슷한 의미)는 반드시 {1, …, k} 범위 내의 정수들의 조합이어야 합니다. 여기서 k는 배열 a이 갖는 첨자들의 개수입니다. 따라서, 이 함수를 실행한 결과는 배열 a와 같은 크기를 갖지만, 원래의 배열 a의 차원을 사용해서 지정한 perm[j]의 순서대로 j의 차원을 갖는 새로운 재배치된 배열입니다.이 함수가 수행하는 연산이 어떤 것인지를 좀 더 쉽게 이해하기 위해 행렬의 전치(transpose)가 좀 더 일반화된 것이라고 생각하시면 도움이 될 것입니다. 즉, A라는 행렬(행렬은 결국 이중 첨자로 된 (doubly subscripted) 배열이도 합니다.)이 주어지면, 아래의 연산을 수행한 결과인 BA를 전치한 행렬입니다.

> B <- aperm(A, c(2,1))

이 경우의 연산은 좀 더 간단한 함수인 t()를 사용한 것과 같습니다. 따라서, B <- t(A)를 사용하면 동일한 결과를 얻을 수 있습니다.


5.7 행렬의 기능들

위에서 살짝 언급했듯이, 행렬은 이중 첨자를 사용하는 배열입니다. 하지만, 행렬이라는 것은 배열 섹션과 분리해서 따로 설명해야할만큼 중요한 개념입니다. R은 행렬에 특화된 다양한 연산기능과 함수들을 제공합니다.몇가지 예를들면, 위에서 설명했던 t(X)는 행렬을 전치하는데 사용되는 함수이며, nrow(A)ncol(A)은 각각 행렬 A의 행과 열의 개수를 알려주는 함수입니다.


5.7.1 행렬의 곱셈

The operator %*% is used for matrix multiplication. 보통은 n1열의 행렬이나 1n열의 행렬은 상황에 따라 적절히 n-벡터로 사용될 수 있습니다. 하지만, 행렬의 곱셈식에서 사용되는 벡터는 곱셈을 수행하기 적합한 조건을 갖추기위해 (행렬의 곱셈을 수행하기 위해서는 앞 행렬의 행의 길이가 뒷행령의 열의 길이가 같아야 합니다.) 행벡터나 열백터로 자동적으로 변환됩니다. (그러나, 나중에 보게 되겠지만, 이러한 행이나 열 벡터로의 변환이 항상 가능한 것은 아닙니다.)

만약, AB 모두 정방(square)행렬이라면, 다음의 식을 사용해서 원소단위별 곱셈을 수행할 수 있습니다.

> A * B

하지만, 아래의 표현은 원소단위별 곱셈이 아닌 행렬의 곱셈이라는 것을 구분하셔야 합니다.

> A %*% B

만약, x가 벡터라면 아래의 표현은 이차식(quadratic form)을 나타냅니다.

> x %*% A %*% x

14

함수 crossprod()는 “외적, 크로스프로덕트 (crossproduct)”라고하며, 연산을 위해 corssprod(X, y)의 형태로 입력하면, 좀 더 효율적인 방법으로 t(X) %*% y와 같은 연산을 수행합니다.만약 함수 crossprod()에 두번째가 인자가 생략되어 있다면, 첫번째 인자를 두 번 사용하여 연산을 수행하게 됩니다.

함수 diag()는 입력받는 인자에 따라 다른 결과를 출력합니다. 만약 diag(v)와 같이 v라는 벡터 인자가 입력되면, 벡터 v의 각 구성요소를 대각원소로 갖는 대각행렬을 생성합니다.반면에 diag(M)과 같이 M라는 행렬 인자가 입력되면, 행렬 M이 가지는 대각원소들을 벡터의 형식으로 출력하게 됩니다.이것은 MATLAB에서 사용하는 함수 diag()과 비슷하게 작동한다고 보시면 됩니다.다소 혼란스러울 수도 있겠지만, diag(k)와 같이 k라는 스칼라 인자가 입력되면, kk열을 가지는 단위행렬(identity matrix)이 생성된다는 점도 기억하시기 바랍니다.


5.7.2 선형방정식과 역행렬

선형방정식을 푼다는 것의 의미는 역행렬을 곱하는 것과 같습니다. 아래의 표현식이 주어지고, 행렬 A와 벡터 b만 알고 있는 경우, 벡터 x가 선형방정식의 해가 됩니다.

> b <- A %*% x

R에서는 아래와 같은 방법으로 선형방정식을 풀어서, x를 해로 구합니다. (약간의 정확도의 차이가 발생하는 경우도 있습니다.)

> solve(A,b)

선형방정식을 좀 더 수학적으로 표현하면 x = A^{-1} %*% b 입니다. 여기에서 A^{-1}은 행렬 A의 역행렬이며, 아래의 함수로 계산할 수 있습니다.

solve(A)

하지만, 위와 같이 역행렬을 이용하여 x <- solve(A) %*% b를 계산하는 것은 함수 solve(A,b)를 사용하는 것보다 비효율적인데다 에러 발성이 가능성도 많아 실제로 많이 사용하지는 않습니다.

다변량의 연산에 사용되는 이차행렬식(quadratic form)  x %*% A^{-1} %*% x  은 A의 역행렬을 이용하는 것 보단 x %*% solve(A,x)으로 계산하는 편이 낫습니다. 15


5.7.3 고유값과 고유벡터

함수 eigen(Sm)는 대칭행렬 (symmetric matrix) Sm 의 고유값(eigenvalues)과 고유벡터 (eigenvectors)를 계산해주며 아래처럼 사용합니다.

> ev <- eigen(Sm)

위 식을 실행한 결과로 ev$val라는 Sm의 고유값 벡터와 여기에 대응되는 ev$vec라는 고유벡터의 행렬을 구성요소로 갖는 리스트를 객체 ev에 저장합니다. 만약 단순히 고유값만 필요하다면 아래와 같이 하시면 됩니다:

> evals <- eigen(Sm)$values

evals이라는 객체는 고유값의 벡터만 포함하고 있을 뿐, 고유벡터는 저장되지 않았습니다.

> eigen(Sm)

행렬의 크기가 큰 경우에는, 다음과 같이 식을 사용함으로써 고유벡터의 계산을 생략하는 편이 나을 수 있습니다.

> evals <- eigen(Sm, only.values = TRUE)$values

5.7.4 특이값 분해 및 행렬식

함수 svd(M)M이라는 임의의 행렬을 인자로 가지며 이 행렬에 대한 특이값 분해(the singular value decomposition)를 수행합니다.이 연산의 결과는 세가지 부분으로 구성됩니다; 첫째는 M행렬의 열공간(column space)과 동일한 공간을 생성(span)하는 정규직교(orthonormal)열 벡터들로 구성된 행렬 U이고; 둘째는 이 행렬의 열공간(column space)이 M 행렬의 행공간(row space)과 동일한 공간을 생성(span)하는 정규직교(orthonormal)열 벡터들로 구성된 행렬 V; 셋째는 M = U %*% D %*% t(V)라는 조건을 만족하는 양의 숫자들로 구성된 대각행렬 D입니다. svd(M)의 실행결과는 위의 세가지를 구성요소로 갖는 하나의 리스트이며, 각 구성요소들은 정의된대로 d, u, v라는 이름을 가집니다.

만약 행렬 M이 정방(square)행렬이라면, 아래처럼 표현식을 사용하여 행렬 M의 행렬식(determinant)의 절대값을 계산할 수 있습니다.

> absdetM <- prod(svd(M)$d)

또한, 여러 행렬에 같은 계산을 반복적으로 사용하고 싶다면 아래와 같이 사용자 정의함수 abdet()를 작성하는 것도 가능할 것입니다. 이렇게 absdet() 함수를 정의해두면, 다른 R 함수처럼 필요할 때마다 사용할 수 있습니다.

> absdet <- function(M) prod(svd(M)$d)

약간은 단순하지만 유용하게 사용할 수 있는 또 다른 예로, 정방(square) 행렬의 트레이스(trace)를 계산해주는 tr() 함수를 작성하는 것도 생각해 볼 수 있습니다.[힌트:이 함수를 작성할 때 loop 문장을 사용할 필요가 없습니다. diag() 함수를 다시 찾아 보세요.]

R은 행렬식(determinant)과 그 부호(sign)을 구하는데 사용하는 det를 빌트인(builtin)함수로 제공합니다. 또다른 함수 determinant는 행렬식의 부호 뿐 아니라 모듈러스(modulus)(그리고 옵션으로 선택시 log 스케일에서의 모듈러스까지)의 결과도 함께 출력합니다. 이러한 함수들에 대해서는 나중에 좀 더 자세히 다루겠습니다.


5.7.5 최소제곱법과 QR 분해법

함수 lsfit()은 최소제곱법 적합(least squares fitting)을 수행하여 얻은 결과들을 리스트 형태로 돌려줍니다.

> ans <- lsfit(X, y)

만약, y가 관측값 벡터이고, X는 디자인 행렬이라고 할때, 아래와 같이 사용된 함수 lsfit()는 최소 제곱법 (least square)을 이용하여 적합한 값을 ans에 할당합니다.더 자세한 사항은 도움말을 참조하시길 바랍니다. 특히, 최소제곱법을 이용한 회귀분석에 대한 모형진단이 필요하시면 함수 ls.diag()를 찾아보시길 바랍니다. 특히, 이 함수를 사용해서 회귀모형을 적합하면, 원래 X의 열에 포함되지 않는 전체 평균이 하나의 항으로 포함된다는 점을 주의하시기 바랍니다. 더욱이 회귀분석을 수행할 때는 거의 대부분의 경우 lsfit() 보다는 lm(.)를 사용하는 것이 더욱 편리하다는 점도 알아두시면 좋을 것입니다.

최소제곱법과 연관되어 있는 함수로는 qr()과 그에 연관된 함수족(allies)이 있습니다. 아래의 예제를 살펴보세요.

> Xplus <- qr(X)
> b <- qr.coef(Xplus, y)
> fit <- qr.fitted(Xplus, y)
> res <- qr.resid(Xplus, y)

위 문장들은 벡터 yX 공간 위에 직사영(orthogonal projection)시킨 값(즉, fitted 된 값)을 fit에, 그리고 그 직교여공간에 사영(the projection onto the orthogonal complement)시킨 값 (즉, 잔차)를 res에, 그리고 사영을 통해 얻은 회귀계수(coefficient)의 벡터는 b에 저장합니다. 특히, b의 값은 MATLAB에서 ‘백슬래쉬’ 연산자를 이용해서 얻은 것과 동일합니다.

위의 연산을 위한 X가 이 full column rank라는 조건을 만족해야 하는 것은 아닙니다.이 조건이 만족되지 않는 경우, 선형독립이 아닌 열들을 찾아서 이들을 제거하면 됩니다.

이런식으로 회귀계수를 계산하는 것은 앞에서 소개된 함수들을 이용하는 것 보다 훨씬 오래되고, 덜 자동화된 (low-level) 방법으로 최소제곱 적합법을 이용하는 방법입니다. 이런 식의 계산이 필요한 경우가 아직 가끔 있긴하지만, 거의 대부분의 경우 앞으로 Statistical models in R (R에서 사용되는 통계모형들)에서 좀 더 설명하게 될 통계 모형 함수들을 사용하는 것으로 대체되고 있습니다.


5.8 cbind()rbind()를 이용하여 분할된 행렬을 조합하기

위에서도 잠깐 언급했었지만, cbind()rbind()라는 함수는 벡터와 행렬을 묶어 새로운 행렬을 생성할 때 사용됩니다. 간단히 말해, cbind() 함수는 여러 행렬들을 세로로, 혹은 열방향으로 묶어서, 그리고 rbind() 함수는 가로로, 혹은 행방향으로 묶어서 새로운 행렬을 생성합니다.

아래 함수 cbind()에 사용될 입력인자는 임의의 길이를 가진 벡터이거나 같은 길이의 열,또는 같은 수의 행을 가진 행렬이어만 합니다. 이 함수를 적용하면 입력된 arg_1, arg_2, …이 각각의 열로 하는 하나의 행렬이 생성됩니다.

> X <- cbind(arg_1, arg_2, arg_3, …)

cbind()의 입력인자가 함께 입력된 다른 행렬의 열 길이 보다 짧은 길이를 가진 벡터인 경우가 있을 수 있습니다.이 경우, 길이가 더 짧은 벡터들은 행렬의 열의 길이(만약 행렬이 입력되지 않은 경우에는 가장 길이가 긴 벡터)에 맞추기 위해 그 구성요소를 반복 사용합니다.

함수 rbind()는 함수 cbind()와 유사한 기능을 행에 대해 수행힙니다.

이 함수의 경우, 입력된 벡터가 무엇이든 간에, 길이가 다를 경우 위와 같이 반복 사용되서 길이를 맞추는 것은 물론이고, 모든 인자를 행벡터로서 처리합니다.

X1X2라는 두 행렬이 같은 개수의 행을 가지고 있다고 가정합니다. 1로 구성된 열과 함께 위 둘을 열 방향으로 결합하여 새 행렬 X를 생성하기 위해, 아래와 같은 명령문을 사용할 수 있습니다.

> X <- cbind(1, X1, X2)

rbind()이나 cbind()를 사용하면 얻어지는 결과는 항상 행렬입니다. 따라서, cbind(x)rbind(x)는 벡터 x를 각각 하나의 열 혹은 하나의 행으로 구성된 행렬로 바꾸는 가장 단순한 방법일 것입니다.


5.9 배열에서 사용하는 결합(concatenation) 함수 c()

cbind()rbind() 함수의 경우 행렬이 가진 dim 속성에 기반해서 여러개의 행렬을 하나로 연결하는 반면, 함수 c()dimdimnames 속성 모두를 무시한 채 결합시킨다고 할 수 있습니다. 따라서, 경우에 따라서는 c()를 이용해야만 할 수 있습니다.

이런식으로 배열의 속성을 무시하고 단순 벡터로 강제형변환하는 공식적으로 알려진 방법은 다음과 같이 as.vector() 함수를 이용하는 것입니다.

> vec <- as.vector(X)

하지만, 이와 비슷한 결과를 함수 c()의 이러한 부가적 성질을 활용함으로써 얻을 수도 있습니다.

> vec <- c(X)

실제로는 다소 차이점이 있기는 하지만, 둘 중 어떤 함수를 이용하여 이 작업을 수행할 것인가는 단순히 프로그래밍 스타일의 차이일 뿐입니다.


5.10 요인을 이용하여 도수분포표 생성하기

우리는 앞부분에서 데이터를 그룹화하는데 요인 (factor)을 사용할 수 있음을 배웠습니다. 마찬가지로 만약 2개의 요인을 사용하면 2차원 분류(two way cross classification)를 정의할 수 있을 것이고, 더 나아가 k 개의 요인으로 k-차원의 분류가 가능할 것입니다. 함수 table()은 같은 길이를 가진 요인들을 분류해서 빈도분포표를 생성합니다. 즉, k개의 요인이 입력될 경우, 이 함수를 사용한 결과로 k 차원의 빈도의 배열이 생성됩니다.

예를 들어, 입력된 각 데이터가 지역(state)코드인 데이터 벡터인 statef라는 하나의 요인이 존재한다고 가정합시다. 아래의 명령문은 statefr라는 이름으로 샘플의 각 주별 빈도를 요약하는 표를 저장합니다.

> statefr <- table(statef)

이 표에 각 주 별 도수는 수준 (level)의 알파벳 이름순으로 정렬됩니다. 이와 같은 작업을 수행하는 좀 더 간단한 방법은 다음과 같습니다.

> statefr <- tapply(statef, statef, length)

이번에는 입련된 각 데이터가 소득수준 (“income class”)을 의미하는 incomef라는 요인을 가정 합시다. 이 소득수준의 경우, 함수 cut()를 사용해서 다음과 같이 생성할 수 있습니다.

> factor(cut(incomes, breaks = 35+10*(0:7))) -> incomef

위에서 정의한 두 개의 요인에 대해 2차원 빈도표를 생성하면 다음과 같습니다:

> table(incomef,statef)
         statef
incomef   act nsw nt qld sa tas vic wa
  (35,45]   1   1  0   1  0   0   1  0
  (45,55]   1   1  1   1  2   0   1  3
  (55,65]   0   3  1   3  2   2   2  1
  (65,75]   0   1  0   0  0   0   1  0

좀 더 많은 차원을 대상으로 빈도표를 작성하는 것도 이것과 크게 다르지 않습니다.


6 리스트와 데이터 프레임


6.1 Lists (리스트)

R에서 리스트(list)라는 것은 컴포넌트 (components)라고 불리는 일정한 순서로 정렬된 여러 객체들의 집합입니다.

각각의 컴포넌트는 반드시 같은 모드(mode)나 형태(type)일 필요는 없습니다. 예를 들어, 하나의 리스트는 수치형 벡터, 논리형 벡터, 행렬, 복소수 벡터, 문자형 벡터, 함수 이외의 어떤 형태라도 컴포넌트로 포함할 수 있습니다. 리스트를 생성하는 아래의 간단한 예를 살펴보시기 바랍니다:

> Lst <- list(name="Fred", wife="Mary", no.children=3,
              child.ages=c(4,7,9))

리스트에 포함된 컴포넌트들은 항상 숫자로 구분(numbered)되어 있으며, 따라서 각각의 컴포넌트를 이에 해당하는 숫자 (즉, 컴포넌트 인덱스)로 불러내는 것이 가능합니다. 따라서, Lst가 4개의 컴포넌트를 갖는 리스트라면, 각각의 컴포넌트는 각각 Lst[[1]],Lst[[2]], Lst[[3]] 그리고 Lst[[4]]로 불러낼 수 있습니다. 특히, Lst[[4]]가 첨자로 표현되는 구성요소를 가진 벡터인 경우, Lst[[4]][1]는 이 컴포넌트의 첫번째 구성요소를 의미합니다.

Lst가 리스트인 경우, length() 함수를 사용하면 (top level) 컴포넌트의 개수를 알 수 있습니다. 위의 예제를 계속 사용하면, length(Lst)는 4라는 값을 출력할 것입니다.

리스트에 포함된 컴포넌트는 이름(named)으로 불러낼 수도 있는데, 이 경우 해당 컴포넌트의 이름에 해당하는 문자열을 위에서 숫자를 사용할 때 처럼 한 쌍의 이중대괄호 안에 넣어 사용하며, 좀 더 쉽게는 아래와 같은 표현식을 사용하는 것도 가능합니다.

> name$component_name

name는 리스트의 이름이고, 스트링 연산자($) 뒤의 component_name는 컴포넌트의 이름입니다.

이렇게 이름으로 직접 불러내는 방법은 사용자가 해당 컴포넌트의 번호(인덱스)를 기억할 필요없이, 쉽고 정확하게 컴포넌트를 불러낼 수 있는 방법입니다.

위의 예제로 다시 돌아가면,

Lst$name이라는 것은 Lst[[1]]와 동일하고, "Fred"라는 값을 가집니다.

Lst$wifeLst[[2]]와 동일하고 "Mary"라는 값을 가집니다.

Lst$child.ages[1]의 경우, Lst[[4]][1]와 동일하며, 4라는 값을 가집니다.

또한, 리스트의 컴포넌트 이름을 이중대괄호 안에 사용하는 것고 가능하며, 따라서 Lst[["name"]]Lst$name은 동일합니다.이러한 사용법은 아래와 같이 리스트 컴포넌트의 이름이 다른 변수로 저장되어 있는 경우에 유용하게 사용될 수 있습니다.

> x <- "name"; Lst[[x]]

리스트를 사용하는데 있어 Lst[[1]]Lst[1]를 구분하는 것은 매우 중요합니다. ‘[[]]’은 리스트 안의 한 개의 컴포넌트를 선택하기위해 사용하는 연산자인 반면,‘[]’은 일반적인 첨자로 사용되는 연산자입니다.따라서, 전자는 리스트 Lst의 첫번째 컴포넌트를 나타내므로, 만약 그 컴포넌트에 이름이 있어도 이름과 상관없이 해당 컴포넌트만을 불러냅니다. 하지만 후자는 리스트 Lst의 첫번째 구성요소만을 갖는 서브리스트(sublit)이므로, 이 구성요소에 이름이 있다면, 이름이 해당 서브리스트와 함께 불러집니다.

컴포넌트들의 이름은 각각의 이름이 구분할 수 있는 최소한의 글자수로 된 약어로 나타내질 수 있습니다. 예를들면, 리스트 Lstcoefficientscovariance라는 이름의 두 개의 컴포넌트로 구성된 경우, Lst$coeLst$cov으로 간소화하여 불러낼 수 있습니다.

사실 컴포넌트들의 이름으로 구성된 벡터는 단순히 리스트의 속성 중 하나라고 볼 수 있으며, 다른 속성들처럼 다룰 수 있습니다. 물론 리스트를 제외한 다른 객체들 역시 names을 속성의 하나로 포함할 수 있습니다.


6.2 리스트를 생성과 수정

이미 만들어놓은 여러개의 객체를 list() 함수를 사용하여 새로운 리스트로 생성할 수 있습니다.

> Lst <- list(name_1=object_1, , name_m=object_m)

아래와 같은 할당문을 사용하면, (사용자가 자유롭게 선택한) object_1, , object_m와 같은 이름을 갖는 m 개의 컴포넌트로 구성된 리스트 Lst를 생성합니다. 만약 이렇게 이름을 할당하는 과정이 생략되면, 컴포넌트들은 숫자로만 구분됩니다. 새로운 리스트가 생성될 때 기존의 객체들은 단순히 컴포넌트로서 복사된 것이기 때문에 새로운 리스트의 생성이 기존의 객체에 아무런 영향을 주지 않습니다.

리스트에 새로운 컴포넌트를 추가하고 싶을 경우, 아래와 같이 첨자를 이용하는 것도 가능합니다.

> Lst[5] <- list(matrix=Mat)

6.2.1 Concatenating lists (리스트 연결하기)

여러개의 리스트를 하나로 묶고 싶은 경우, 아래와 같이 함수 c()를 이용하면 입력된 순서대로 하나로 묶인 리스트가 생성됩니다.

> list.ABC <- c(list.A, list.B, list.C)

앞 부분에서 연결함수를 사용해서 입력인자인 벡터들을 모두 연결해서 하나의 벡터로 생성했던 것과 비슷합니다. 다만, 리스트를 연결할 경우, dim을 포함한 모든 리스트의 속성이 무시된 채 작업된다는 점 정도의 차이가 있을 뿐 입니다.


6.3 Data frames (데이터 프레임)

데이터 프레임 (data frame)"data.frame"이라는 클래스를 가진 리스트입니다.하지만 데이터 프레임을 리스트와 구분짓는 다음과 같은 몇가지 특징이 있습니다.

많은 경우, 데이터 프레임이라는 것은 모드(mode)와 속성(attribute)이 조금 다른 행렬이 하나로 보아도 무방합니다. 따라서 행렬에서 했던 것 처럼, 행렬 인덱스를 사용하여 데이터 프레임을 행이나 열 중 일부를 임의로 선택할 수 있습니다.


6.3.1 데이터 프레임 생성하기

데이터 프레임의 열 (또는 컴포넌트)를 구성하게 될 객체들의 위에서 언급한 조건들을 충족시키면, 다음과 같이 data.frame 함수를 사용하여 데이터 프레임을 생성할 수 있습니다.

> accountants <- data.frame(home=statef, loot=incomes, shot=incomef)

위의 예제에서 사용된 statef는 이산형 데이터 벡터이고, incomes는 연속형 데이터 벡터, 그리고 incomef는 범주화된 값을 갖는 벡터입니다. 따라서 새로 생성될 데이터 프레임 accountantshome, loot, 그리고 shot라는 세 변수로 구성되는데, 벡터 statefhome라른 변수로, 벡터 incomesloot라는 변수로, 마지막으로 벡터 incomefshot라는 변수로 저장됨을 의미합니다.컴포넌트들이 위와 같은 데이터 프레임으로써의 요건을 만족하는 리스트라면 함수 as.data.frame()를 사용하여 데이터 프레임으로 강제형변환 (coerced)시키는 것이 가능합니다.

이미 저장된 데이터를 가져와 데이터 프레임을 생성하기 위한 가장 쉬운 방법은 외부 파일에서 데이터를 읽어들일 때 사용하는 read.table() 함수를 사용하는 것 겁니다.이 함수에 대해서는 Reading data from files (파일로부터 데이터 읽어오기)편에서 더 자세히 다루도록 하겠습니다.


6.3.2 attach() and detach()

스트링($) 연산자는, accountants$home와 같이 리스트의 컴포넌트를 불러내기 위해 사용하지만 이 방법이 언제나 가장 편리한 것은 아닙니다. (특히 구성요소가 많은 경우라면,) 리스트나 데이터 프레임의 구성요소들의 이름을 필요한 동안만 변수이름처럼 나열해서 쓸 수 있도록하면, 한번에 하나씩 리스트 상의 이름을 사용해서 컴포넌트를 불러내는 번거로움을 피할 수 있습니다.

attach() 함수의 경우, 리스트나 데이터 프레임과 같은 형태의 ’데이터베이스(database)’를 인자로 받습니다. 따라서, 세개의 변수 lentils$u, lentils$v, lentils$w로 구성된 데이터 프레임lentils을 존재하고 여기에 attach() 함수를 사용하면, 해당 데이터 프레임의 탐색경로(search path)가 position 2로 바뀌며, 이것은 변수 u, v, w를 담지 않는 경로인 position 1,작업 와 별개이므로, attach 함수가 적용된 데이터 프레임의 구성요소인 u, v, w변수들을 이들의 이름만으로(별도의 스트링 연산자나 인덱스를 사용하지 않고) 불러내는 것이 가능해집니다.

> attach(lentils)

attach()를 사용시 주의할 점은, 다음과 같이 할당문을 사용할 경우, 이미 존재하던 데이터 프레임 내 컴포넌트인 u가 연산의 결과물로 대체된다기 보다는, 탐색경로 상의 position 1,에서 현재 작업 디렉토리에 새로운 변수 u가 생성되어 이미 존재하는 변수를 가로막게된다는 것 입니다. (따라서 위 명령문을 실행하면 lentils내 변수 vw의 더하기 연산의 결과가 u라는 이름의 객체가 되지만, 이 객체가 데이터 프레임 lentils내의 u로 저장되지는 않습니다. attach() 사용이후의 연산은 최상위 탐색경로인 position 1에서 이루어지므로 데이터 프레임이 위치하는 position 2에 있는u가 영향을 받지 않기 때문입니다.)

> u <- v+w

만약, 데이터 프레임 자체에 변경된 내용을 영구 저장하고싶다면, $ 연산자를 사용하여 다음과 같이 따로 저장해야 합니다:

> lentils$u <- v+w

하지만, 이렇게 컴포넌트 u에 새로 저장된 값들은 데이터 프레임을 (detach()함수를 사용해서) 분리(detach)한 후 다시 (attach() 함수로) 불러들이는(attach) 과정을 통해서 확인할 수 있습니다.

데이터 프레임을 현재 경로에서 다시 분리(detach)시키기 위해, 다음과 같이 detach() 함수를 사용할 수 있습니다.)

> detach()

좀 더 정확하게 설명하면, 이 함수는 position 2 상에 위치한 현재 작업 중인 개체(데이터 프레임)을 이 경로에서 분리시키는 역할을 합니다. (즉, 경로가 position 1로 재변경 됩니다.) 따라서, 데이터 프레임을 분리하고 난 후의 현재 작업상황(context)에서는, 따로 lentils$u와 같이 지정하지 않는한, 변수 u, v and w을 사용하는 것이 더이상 가능하지 않습니다. 개체(데이터 프레임)들이 탐색 경로 상 2 보다 큰 숫자의 position에 위치할 경우, 이들을 해당 경로에서 분리(detach)하기위해 detach 함수에 경로 번호를 지정하는 것이 가능합니다. 하지만, 언제나detach(lentils) 또는 detach("lentils")과 같이 데이터 프레임의 이름을 직접 입력하는 편이 실수를 줄일 수 있는 보다 안전한 방법입니다.

Note: R에서 리스트나 데이터 프레임은 반드시 position 2 또는 그 이상의 위치에만 연결할(attach) 수 있습니다. 또, 연결한다(attach)는 것은 존재하는 객체를 복사(copy)해서 가져온다는 의미입니다. 이렇게 연결된(attach) 개체들은할당(assign)을 통하여 변경하는 것이 가능합니다. 하지만, 이 경우 원래의 리스트나 데이터 프레임은 변경된 값에 영향을 받지 않습니다.


6.3.3 데이터 프레임 활용하기

하나의 작업 디렉토리에서 여러 개의 작업을 동시에 수행하는데 도움이 될만한 팁을 하나 드리자면,

이렇식으로 작업 공간을 유지하면, 같은 디렉토리 내에서 x, y, z와 같은 (매우 흔한 이름의) 변수들을 이용해서 여러 작업을 동시에 수행해야 하는 겅우라도 비교적 쉽게 변수들을 다룰 수 있습니다.


6.3.4 Attaching arbitrary lists (임의적인 리스트를 연결하기)

일반함수(generic function)의 하나인 attach()함수는 디렉토리나 데이터 프레임 뿐만 아니라 다른 클래스의 객체를 대상으로도 탐색경로(search path)를 연결(attach)하는 작업을 수행합니다. 특히, 객체의 모드가 "list"인 경우는 데이터프레임과 동일한 방법으로 사용 가능합니다:

> attach(any.old.list)

attach()에 의해서 연결된 객체는 detach 함수에 의해서 분리되며, 이때 해당 위치의 번호나, 좀 더 바람직하게는 해당 객체의 이름을 사용하여 분리될 대상을 구체적으로 지정할 수 있습니다.


6.3.5 탐색경로를 관리하기

search 함수는 현재 탐색경로를 보여줌으로서 사용자가 현재 연결하여 작업하고 있는 데이터 프레임 및 리스트 (그리고 패키지들)를 확인할 수 있도록 해줍니다. 처음으로 search를 수행하면 아래와 같은 결과가 출력됩니다. 여기서 .GlobalEnv라는 것은 현재 작업 중인 작업공간(workspace)을 의미합니다.

> search()
[1] ".GlobalEnv"   "Autoloads"    "package:base"

17.

데이터프레임 lentils을 연결(attached)하고나면, search()는 아래와 같은 결과를 보여줍니다.

> search()
[1] ".GlobalEnv"   "lentils"      "Autoloads"    "package:base"
> ls(2)
[1] "u" "v" "w"

ls 혹은 objects 함수를 이용하여 탐색경로(serach path) 내의 어떤 위치(position 1,2,..)에서나 어떤 객체가 사용 중인지 확인할 수 있습니다. 위에서 함수 ls()안에 사용된 숫자 2는 position 2를 대상으로 한다는 의미입니다.

마지막으로, 사용중인 데이터프레임을 분리(detach)하고나서 탐색경로(search path)에서 정말로 사라졌는지 확인합니다.

> detach("lentils")
> search()
[1] ".GlobalEnv"   "Autoloads"    "package:base"

7 Reading data from files (파일로부터 데이터 읽어오기)

용량이 큰 데이터 객체는 현재 작업하고 있는 R 세션에서 키보드로 입력하는 것보다는 외부에 저장되어 있는 데이터파일을 불러들이는 것이 편리하고 빠른 방법입니다. R의 입력 도구는 단순하여 요구조건이 다소 엄격하고 유연하지 않습니다. R 설계자들에 의해 R에서 데이터를 읽어들일 수 있는 요구사항을 충족시키기 위해 파일에디터(file editor) 혹은 Perl18과 같은 다른 도구를 이용하여 여러분의 입력 파일을 수정할 수 있는 명백한 추측이 있습니다. 일반적으로 이것은 매우 단순합니다.

만약 변수들이 데이터 프레임에서 다루어질 것이라면 (우리가 그렇게 될 것이라고 강하게 가정하는 것과 같이), 전체 데이터 프레임은 read.table() 함수에 의해 직접적으로 읽을 수 있습니다. 직접적으로 호출할 수 있는 보다 근본적인 입력 함수인 scan()도 있습니다.

데이터의 입출력에 관한 더 자세한 사항에 대해서는 R Data Import/Export 문서를 참조하시길 바랍니다.


7.1 read.table() 함수

데이터 프레임 전체를 한번에 불러오기 위해서는, 외부 파일이 특정한 형식을 가지고 있어야만 합니다.

만약, 첫번째 행을 구성하는 항목들의 개수가 두번째 행을 구성하는 항목들의 개수보다 적을 경우, 강제적으로 첫번째 행의 구조에 따라 맞추어지게 됩니다. 따라서 데이터 프레임으로 읽어들일 파일의 처음 몇 줄은 다음과 같이 보여질 것입니다.

Input file form with names and row labels:

     Price    Floor     Area   Rooms     Age  Cent.heat
01   52.00    111.0      830     5       6.2      no
02   54.75    128.0      710     5       7.5      no
03   57.50    101.0     1000     5       4.2      no
04   57.50    131.0      690     6       8.8      no
05   59.75     93.0      900     5       1.9     yes
...

기본적으로 R이 데이터 파일을 읽어올때, (행레이블를 제외하고) 예제와 같이 수치값(numeric item)은 숫자변수(numeric variables)로, 그렇지 않다면 Cent.heat와 같이 요인(factor)으로 비숫자변수(non-numeric variables)로 읽어들입니다.

함수 read.table()는 직접적으로 데이터 프레임을 읽어들이는데 사용될 수 있습니다.

> HousePrice <- read.table("houses.data")

여러분은 종종 행레이블을 직접적으로 포함하는 것을 생략하고 기본값을 사용하길 원하는 경우가 있습니다. 이러한 경우 그 파일에는 아래와 같이 행레이블 열이 생략되어 있을 것입니다.

Input file form without row labels:

Price    Floor     Area   Rooms     Age  Cent.heat
52.00    111.0      830     5       6.2      no
54.75    128.0      710     5       7.5      no
57.50    101.0     1000     5       4.2      no
57.50    131.0      690     6       8.8      no
59.75     93.0      900     5       1.9     yes
...

이런 경우에는 아래와 같이 read.table() 함수를 사용시 header=TRUE 옵션을 함께 사용합니다.

> HousePrice <- read.table("houses.data", header=TRUE)

header=TRUE 옵션은 첫 번째 줄이 헤더 줄이라는 것을 특정하여 파일의 구조로부터의 의미에 의해 명시적인 행레이블이 주어지지 않았다는 것을 나타냅니다.


7.2 scan() 함수

데이터 벡터들이 같은 길이를 가지고 있고 이들은 동시에 병렬적으로 읽어들여진다고 가정해 보십시오. 그리고 벡터의 개수는 세개인데 첫번째 벡터는 문자형 모드를 가지고, 나머지 두 벡터는 수치형 모드를 가지며, 이 벡터들은 input.dat라는 파일내에 저장이 되어 있다고 가정합니다. scan()함수를 이용하여 세개의 벡터를 리스트 형식으로서 불러오는 첫 번째 단계는 다음과 같습니다.

> inp <- scan("input.dat", list("",0,0))

scan()함수의 두번째 인자는 어떤 모드(mode)로서 그 세 가지 벡터들을 읽어올 것인가에 대한 더미 리스트 구조(dummy list structure)입니다. inp에 담겨진 결과는 그것의 구성요소가 읽혀진 세 벡터들인 리스트 입니다. 데이터 값들(data items)을 세 개의 구분된 벡터로 분해하기 위해서 다음과 같이 할당(assignments)을 이용합니다.

> label <- inp[[1]]; x <- inp[[2]]; y <- inp[[3]]

위에서 소개한 방법보다 더 편한 방법은 아래에서 보는 것과 같이 더미 리스트 구조를 사용할 때 바로 이름을 부여하는 것입니다. 그러한 경우 그 이름들은 읽혀진 벡터들에 접근하는데 사용될 수 있습니다. 예를 들어 다음과 같습니다.

> inp <- scan("input.dat", list(id="", x=0, y=0))

여러분이 각각의 변수들에 접근하길 원한다면 그것들은 다음과 같이 워킹프레임(the working frame)에서 변수들에 재할당(re-assigned)되거나

> label <- inp$id; x <- inp$x; y <- inp$y

또는 그 리스트가 탐색경로의 position 2에 첨부될 수 있습니다(이에 대해서는 see Attaching arbitrary lists (임의적인 리스트를 연결하기)를 참고하시길 바랍니다).

만약, 아래와 같이 두번째 인자가 리스트가 아닌 단일 숫자값이라면, 하나의 벡터가 읽혀지게 됩니다. 그리고 반드시 벡터의 모든 구성요소는 더미 값(dummy value)과 같이 동일한 모드를 가지고 있어야 합니다.

> X <- matrix(scan("light.dat", 0), ncol=5, byrow=TRUE)

더욱 정교한 입력 도구들이 사용가능하며 매뉴얼에 설명되어 있습니다.


7.3 내장된 데이터셋을 이용하기

R은 기본적으로 대략 100여개의 데이터셋을 datasets 패키지를 통하여 제공하고 있고 (R과 함께 제공되는 추천 패키지를 포함하여) 다른 것들이 패키지들에 따라 사용가능합니다. 현재 사용가능한 데이터셋의 목록을 확인하고 싶으시다면 아래와 같이 data()함수를 이용하시면 됩니다.

data()

R 버전 2.0.0 부터 R과 함께 제공되는 모든 데이터셋은 아래에서 보여지는 것과 같이 데이터셋의 이름을 통하여 바로 접근이 가능합니다. 그러나 많은 패키지들이 아직 이전의 R로 데이터세트를 로드하는데 사용되었던 data 방법을 사용하고 있습니다. 예를 들어, 다음과 같습니다.

data(infert)

그리고 이것은 여기에서의 사례와 같이 표준패키지에서도 아직까지 사용될 수 있습니다. 대부분의 경우 이것은 동일한 이름의 R 객체를 로드할 것입니다. 그러나 몇몇의 사례에서 그것은 여러 객체를 로드하므로 로드될 것으로 기대되는 확인하기 위해 객체에 대한 온라인 도움말을 참고하시기 바랍니다.

7.3.1 다른 R 패키지들로부터 데이터를 로딩하기

만약 특정 패키지 내에 제공되어지는 데이터에 접근하고 싶다면 아래와 같이 data()함수의 package라는 인자를 사용합니다.

data(package="rpart")
data(Puromycin, package="datasets")

만약 특정 패키지가 library 함수를 이용하여 현재의 작업공간에 연결이 되어 있다면, 패키지에 내장된 데이터셋들은 자동으로 검색되게 됩니다.

User-contributed packages can be a rich source of datasets.


7.4 데이터를 편집하기

만약 사용자가 데이터 프레임이나 행렬의 일부내용을 수정 및 편집을 하고 싶을때 edit는 편집을 위하여 구분된 스프레드시트와 같은 환경을 가져옵니다. 이것은 한 번 불러온 데이터세트에 작은 변화를 주는데 유용합니다. 명령은 다음과 같습니다.

> xnew <- edit(xold)

edit()함수는 데이터셋 xold을 편집한 뒤, 편집된 새로운 내용을 새로운 데이터셋 xnew로 저장한다는 의미입니다. 만약, 사용자가 원본 데이터셋 xold 자체를 변경하고자 한다면 가장 단순한 방법은 fix(xold) 함수를 이용하는 것인데 이것은 xold <- edit(xold)와 동일한 표현입니다.

Use

> xnew <- edit(data.frame())

만약에 여러분이 비어있는 데이터 프레임으로부터 윈도우즈 기반의 스프레드시트를 통하여 새로운 데이터를 입력하고자 한다면 아래와 같이 할 수 있습니다.


8 확률분포함수


8.1 통계분포표들을 한데 묶어 놓은 R

R의 많은 장점들 중 한가지는 다양한 통계분포표를 제공하는 것입니다. P(X <= x)을 알려주는 누적확률(cumulative probability)값, 주어진 확률함수로부터 밀도(density)계산, 주어진 q에 해당하는 퀀타일(quantile)을 계산, P(X <= x) > q)라는 조건을 만족하는 x값 찾기 및 주어진 분포로부터의 난수를 생성할 수 있습니다.

DistributionR nameadditional arguments
betabetashape1, shape2, ncp
binomialbinomsize, prob
Cauchycauchylocation, scale
chi-squaredchisqdf, ncp
exponentialexprate
Ffdf1, df2, ncp
gammagammashape, scale
geometricgeomprob
hypergeometrichyperm, n, k
log-normallnormmeanlog, sdlog
logisticlogislocation, scale
negative binomialnbinomsize, prob
normalnormmean, sd
Poissonpoislambda
signed ranksignrankn
Student’s ttdf, ncp
uniformunifmin, max
Weibullweibullshape, scale
Wilcoxonwilcoxm, n

위의 표를 잘 살펴보면 하나의 규칙을 알 수 있습니다. ‘d’로 시작하는 함수명은 확률밀도(density)를 구하기 위해 사용이 되고,‘p’로 시작하는 함수명은 누적확률값(cumulative probability)를 구하기 위해 사용이 되며,‘q’로 시작하는 함수명은 퀀타일(quantile)을 구하며,‘r’로 시작하는 함수명은 시뮬레이션을 위한 난수를 생성하는데 사용됩니다.또한, dxxx의 첫번째 인자는 x이며,pxxxq, qxxxp,rxxxn입니다(rhyper, rsignrank 그리고 rwilcox의 경우에는 nn입니다).모든 함수에 non-centrality parameter(비중심화 모수)인 ncp를 사용할 수 있는 것은 아니므로 보다 더 자세한 사항은 온라인 도움말을 참고하십시오.

pxxxqxxx 함수들은 모두 lower.taillog.p라는 논리인자(logical arguments)를 가지며, dxxx는 인자 log를 가집니다. 이러한 옵션의 사용은 아래에서 보이는 바와 같은 방법으로 생존분석(survival analysis)에서 사용되는 H(t) = -log(1-F(t))이라는 누적 hazard 함수의 계산을 가능하게 합니다.

 - pxxx(t, ..., lower.tail = FALSE, log.p = TRUE)

또한, dxxx(..., log = TRUE)와 같은 인자의 설정은 직접적으로 더 정교한 로그우도(log-likelihood) 값을 얻을 수 있도록 해줍니다.

더 나아가 정규분포로부터 얻은 샘플에 대해서 표준화된 범위에 대한 분포를 함수 ptukeyqtukey를 통하여 얻을 수 있습니다. 또한, 멀티노미얼 (multinomial) 분포에 대한 밀도값과 난수생성은 dmultinomrmultinom이라는 함수를 통하여 얻을 수 있습니다. 더 많은 분포에 대해서는 SuppDists라는 사용자개발패키지(contributed packages)를 찾아보시길 바랍니다.

밀도함수를 활용하는 두 가지 예제입니다.

> ## 2-tailed p-value for t distribution
> 2*pt(-2.43, df = 13)
> ## upper 1% point for an F(2, 7) distribution
> qf(0.01, 2, 7, lower.tail = FALSE)

R에서 어떻게 난수를 생성하는지 알고 싶으시다면 온라인 도움말 RNG를 살펴보시길 바랍니다.


8.2 데이터의 분포 살펴보기

많은 방법을 통하여 주어진 (일변량) 데이터세트의 분포를 확인해 볼 수 있습니다. 가장 쉬운 방법은 함수 summary 혹은 fivenum를 이용하여 약간 다른 의미의 수치적 요약정보를 살펴 보는 것입니다. 그리고 stem 함수를 이용하여 "줄기-잎" 그림("stem and leaf" plot)을 이용하여 확인해 볼수도 있습니다.

> attach(faithful)
> summary(eruptions)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max.
  1.600   2.163   4.000   3.488   4.454   5.100
> fivenum(eruptions)
[1] 1.6000 2.1585 4.0000 4.4585 5.1000
> stem(eruptions)

  The decimal point is 1 digit(s) to the left of the |

  16 | 070355555588
  18 | 000022233333335577777777888822335777888
  20 | 00002223378800035778
  22 | 0002335578023578
  24 | 00228
  26 | 23
  28 | 080
  30 | 7
  32 | 2337
  34 | 250077
  36 | 0000823577
  38 | 2333335582225577
  40 | 0000003357788888002233555577778
  42 | 03335555778800233333555577778
  44 | 02222335557780000000023333357778888
  46 | 0000233357700000023578
  48 | 00000022335800333
  50 | 0370

실은 줄기-잎 그림은 히스토그램과 비슷하며 R은 히스토그램을 제공하는 hist 함수를 가지고 있습니다.

> hist(eruptions)
## make the bins smaller, make a plot of density
> hist(eruptions, seq(1.6, 5.2, 0.2), prob=TRUE)
> lines(density(eruptions, bw=0.1))
> rug(eruptions) # show the actual data points

위의 예제에서 사용된 것과 같이 히스토그램보다 좀 더 정교한 밀도그림(density plot)은 density 함수에 의해서 얻을 수 있고 우리는 이 예제에서 density에 의해 만들어진 선을 추가하였습니다. density함수의 bw(bandwidth) 인자의 값은 trial-and-error를 통해 얻어집니다. (Bandwidth의 선택에 있어서 자동화된 방법이 있는데, bw='SJ'를 이용해보시길 바랍니다).

images/hist

ecdf 함수를 이용하여 경험적 누적 분포 함수(empirical cumulative distribution function)를 그려 볼 수 있습니다.

> plot(ecdf(eruptions), do.points=FALSE, verticals=TRUE)

이 분포는 표준정규분포와는 많은 차이가 있음을 명백히 알 수 있습니다. 하지만, 화산폭발이 3분이상 지속될 경우에 대한 분포는 어떨까요? 3분이상의 데이터으로부터의 생성된 누적분포를 만들어 본뒤 그 위에 정규분포와 겹쳐봄으로서 비교해봅니다.

> long <- eruptions[eruptions > 3]
> plot(ecdf(long), do.points=FALSE, verticals=TRUE)
> x <- seq(3, 5.4, 0.01)
> lines(x, pnorm(x, mean=mean(long), sd=sqrt(var(long))), lty=3)
images/ecdf

Q-Q 플랏을 이용하여 화산폭발 3분이상의 데이터에 대한 정규성을 검토해보는 것도 도움이 됩니다.

par(pty="s")       # arrange for a square figure region
qqnorm(long); qqline(long)

Q-Q 플랏으로부터 오른쪽 꼬리 부분이 생각보다 짧은 것을 제외하고는 정규분포를 대체적으로 따르는 것 같습니다. 그럼 t-분포함수로부터 생성된 난수의 분포와는 어떤 관계를 가질지 비교해 보십시오.

images/QQ
x <- rt(250, df = 5)
qqnorm(x); qqline(x)

t-분포로부터 얻어진 난수의 분포가 정규분포의 꼬리보다 길다는 것을 알 수 있습니다. 우리는 다음과 같은 방법으로 생성된 분포에 대한 Q-Q plot을 만들어 볼 수 있습니다.

qqplot(qt(ppoints(250), df = 5), x, xlab = "Q-Q plot for t dsn")
qqline(x)

마지막으로 정규성과 얼마나 따르는지를 확인하는 테스트를 수행하고자 할 것입니다. R은 아래와 같은 Shpiro-Wilk 테스트를 제공합니다.

> shapiro.test(long)

Shpiro-Wilk 테스트 외에도 Kolmogorov-Smirnov 테스트를 이용하여 정규성을 확인해 볼 수 있습니다.
data:  long
W = 0.9793, p-value = 0.01052

and the Kolmogorov-Smirnov test

> ks.test(long, "pnorm", mean = mean(long), sd = sqrt(var(long)))

         One-sample Kolmogorov-Smirnov test

data:  long
D = 0.0661, p-value = 0.4284
alternative hypothesis: two.sided

(여기에서는 우리가 같은 표본으로부터 정규분포의 모수를 추정해왔던 것과 같은 분포 이론은 적용되지 않음에 유의하십시오.)


8.3 일표본과 이표본 검정

지금까지 하나의 표본을 정규분포와 비교해 보았습니다. 두 개의 샘플을 비교하고자 한다면 더 많은 작업이 요구될 것입니다. R에서는 다음 예제에 사용되는 통계적 테스트를 포함하여 모든 전형적인 테스트들을 stats 패키지에 넣어두었습니다.

1995년에 Rice가 the latent heat of the fusion of ice (cal/gm)에 대해서 연구한 논문의 490 쪽에 게재된 내용을 고려해 보시기 바랍니다. 다음 두 개의 데이터셋이 이용되었습니다.

Method A: 79.98 80.04 80.02 80.04 80.03 80.03 80.04 79.97
          80.05 80.03 80.02 80.00 80.02
Method B: 80.02 79.94 79.98 79.97 79.97 80.03 79.95 79.97

박스플랏(boxplot)은 두 개의 샘플에 대하여 간단한 시각적 비교를 제공합니다.

A <- scan()
79.98 80.04 80.02 80.04 80.03 80.03 80.04 79.97
80.05 80.03 80.02 80.00 80.02

B <- scan()
80.02 79.94 79.98 79.97 79.97 80.03 79.95 79.97

boxplot(A, B)

첫번째 그룹이 두번째 그룹보다 더 높은 결과를 보여주는 것같습니다.

images/ice

각각의 데이터의 평균이 같은지를 테스트하기 위해서 아래와 같이 unpaired t-테스트를 수행해 봅니다.

> t.test(A, B)

         Welch Two Sample t-test

data:  A and B
t = 3.2499, df = 12.027, p-value = 0.00694
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 0.01385526 0.07018320
sample estimates:
mean of x mean of y
 80.02077  79.97875

테스트의 결과는 평균의 차이가 정규분포를 따른다고 가정할때 통계적으로 의미가 있음을 나타내고 있습니다. 여기에서 한가지 알아야 할 점은 R은 기본적으로 두 데이터의 분산이 같다고 가정하지 않는다는 것입니다. 이것은 S-PLUS에서 제공하는 t.test와 동일합니다. 따라서 두 데이터의 분산이 같은지에 대해서 F-테스트를 시행해 보아야 할 것입니다. 이 때, 두 데이터는 정규분포로부터 얻어진 샘플이라고 가정합니다.

> var.test(A, B)

         F test to compare two variances

data:  A and B
F = 0.5837, num df = 12, denom df =  7, p-value = 0.3938
alternative hypothesis: true ratio of variances is not equal to 1
95 percent confidence interval:
 0.1251097 2.1052687
sample estimates:
ratio of variances
         0.5837405

테스트의 결과는 두 데이터의 분산은 통계적으로 차이가 없음을 의미하므로, 두 데이터의 분산이 같다고 가정하는 전형적인 t-테스트를 사용해도 무방합니다.

> t.test(A, B, var.equal=TRUE)

         Two Sample t-test

data:  A and B
t = 3.4722, df = 19, p-value = 0.002551
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 0.01669058 0.06734788
sample estimates:
mean of x mean of y
 80.02077  79.97875

모든 테스트들이 두 데이터가 정규분포로부터 얻어진 샘플임을 가정하고 있으나, two-sample Wilcoxon 혹은 Mann-Whitney 테스트에 필요한 가정은 분포가 단순히 연속형이어야 한다는 것입니다.

> wilcox.test(A, B)

         Wilcoxon rank sum test with continuity correction

data:  A and B
W = 89, p-value = 0.007497
alternative hypothesis: true location shift is not equal to 0

Warning message:
Cannot compute exact p-value with ties in: wilcox.test(A, B)

테스트를 수행한 결과에 경고가 있음을 알 수 있습니다. 이것은 아마도 각각의 샘플안에 동일한 값을 가지는 데이터들이 존재하기 때문일것입니다. 따라서 연속형 분포를 가정하기 보다는 데이터가 이산형분포로부터 나왔다고 생각하는게 올바를 것입니다(혹은 이것은 rounding 으로부터 나온 결과일 수 도 있습니다).

두 개의 샘플을 시각적으로 비교해 보는데 여러가지 방법이 있을 수 있습니다. 그 중에서 두 개의 박스플랏을 동시에 비교해보는 것은 이미 해 보았습니다.

> plot(ecdf(A), do.points=FALSE, verticals=TRUE, xlim=range(A, B))
> plot(ecdf(B), do.points=FALSE, verticals=TRUE, add=TRUE)

위에서 사용된 코드는 두개의 emprical CDFs (누적확률분포)를 비교할 것입니다. 또한 qqplot 함수를 이용하여 두 개의 샘플에 대한 Q-Q 플랏을 생성할 수도 있습니다. 아래의 코드는 일반 연속 분포를 가정하여 두 개의 ecdf의 최대수직거리차이(the maximal vertical distance)에 대하여 Kolmogorov-Smirnov 테스트를 수행합니다.

> ks.test(A, B)

         Two-sample Kolmogorov-Smirnov test

data:  A and B
D = 0.5962, p-value = 0.05919
alternative hypothesis: two-sided

Warning message:
cannot compute correct p-values with ties in: ks.test(A, B)

9 그룹화, 반복문, 그리고 조건부 실행


9.1 그룹화된 표현

R은 명령어 형식으로 결과값을 반환하는 함수 또는 표현을 사용하는 점에서 표현언어(expression language)입니다.결과값를 재사용할 수 있도록 표현식에 할당하며, 이 표현식을 어느 곳에서든지 재사용할수도 있고 다중할당도 가능합니다.

또한, {expr_1; ; expr_m}와 같이 여러개의 명령들을 중괄호로 한데 묶어 이것을 또한 표현식으로도 사용할 수 있습니다. 이렇게 중괄호로 묶은 것을 그룹화된 표현식이라고 하고, 이것의 결과는 그룹내의 맨 마지막 명령문이 실행되었을때 얻어지게 됩니다. 이렇게 그룹화된 표현식 역시 더 큰 표현식의 일부분으로도 사용될 수 있습니다.


9.2 제어문


9.2.1 조건부 실행: if

조건문은 아래와 같은 형식을 가집니다.

> if (expr_1) expr_2 else expr_3

expr_1은 반드시 참 혹은 거짓이라는 단 하나의 논리형 값을 가져야만 합니다.

&&||는 종종 if이라는 조건문과 함께 쓰이는 “short-circuit” 연산자입니다.&|가 벡터내 구성요소 단위의 연산을 수행하는 반면, &&||는 길이가 1인 벡터들에만 적용되고 필요한 경우 그것의 두 번째 인자만 평가합니다(evaluate).

R은 벡터라이즈(vectorized)된 버전의 if/else 조건문인 ifelse 함수를 제공하고 있습니다. 이것은 ifelse(condition, a, b)의 형식을 가지고 만약 condition[i] 이 참이면 a[i]를, 거짓이면 b[i]를 결과값으로 가지게 됩니다.


9.2.2 반복적 실행: for를 이용한 반복, repeat 그리고 while

다음은 for 루프를 이용한 반복문에 대한 형식입니다.

> for (name in expr_1) expr_2

name은 루프(loop) 변수입니다. expr_1은 흔히 1:20과 같이 사용되는 계열로 벡터표현식이고 expr_2는 더미(dummy) name의 방법으로 씌여진 하위표현식(sub-expressions)과 함께 그룹화된 표현식인 경우가 종종 있습니다. expr_2expr_1의 벡터결과에서의 값을 통해 name 처럼 반복적으로 평가됩니다(evaluated).

예를들어, 만약 ind가 그룹멤버쉽을 나타낸다면, 각 그룹별로 yx의 관계를 살펴 볼 수 있는 플랏(plot)을 생성하고자 하는 경우를 가정해 봅니다.이를 수행하기 위한 한가지 옵션은 어떤 특정 요인이 가지고 있는 수준별로 플랏을 생성해주는 함수 coplot() 19 을 이용하는 것입니다. 또 다른 방법으로는 아래와 같이 하는 것입니다.

> xc <- split(x, ind)
> yc <- split(y, ind)
> for (i in 1:length(yc)) {
    plot(xc[[i]], yc[[i]])
    abline(lsfit(xc[[i]], yc[[i]]))
  }

위에서 사용된 함수 split()는 주어진 데이터를 특정 요인이 가지는 수준별로 분리한 뒤, 각각의 수준별 데이터를 컴포넌트로 가지는 리스트를 생성합니다.이것은 박스플랏과 많은 연관이 있는 매우 유용한 함수입니다.더 자세한 사항은 도움말 help 기능을 이용하시길 바랍니다.

Warning: R에서는 for()를 이용한 반복문은 다른 컴파일된 언어들에 비하여 자주 사용되지 않습니다. 그 이유는 전체 데이터 객체를 이용하여 벡터라이징 테크닉을 적절히 활용하는 것이 R에서는 for()를 이용한 반복문보다도 더 빠른 연산속도를 가지며, 프로그래머의 입장에서 프로그램을 직관적으로 읽기 쉽고 이해가 빠르게 도와줍니다.

다른 반복기능들은

> repeat expr

문과

> while (condition) expr

문을 가지고 있습니다.

breaknext라는 두 명령문은 반복문을 중단할 때 쓰이지만, 중요한 차이가 있습니다. break는 반복문을 무조건 중단하고 반복문 이후의 명령들을 실행하고자 할때 쓰입니다. 따라서 repeat을 사용하여 expr를 반복하던 중, 이를 중단하고자 할때는 break 명령문을 사용하면 됩니다.

그러나, next는 현재 진행하고 있는 반복 단계만을 건너뛰고 다음 단계의 반복단계로 넘어가라는 의미입니다.

실제로 프로그램의 흐름을 제어하는 것은 대개 사용자 정의함수를 작성할때 다루어집니다. 이에 관련된 예제들에 대해서는 다음의 Writing your own functions (사용자 정의함수 작성하기) 에서 다룰 것입니다.


10 Writing your own functions (사용자 정의함수 작성하기)

R은 방대한 양의 함수를 지원하고 있으나, 사용자가 직접 function(함수)라는 모드를 가진 객체를 생성할 수 있도록 지원합니다. R이 사전에 미리 제공하는 함수들은 내장(built-in)함수라고 하며, 사용자가 직접 정의하는 함수를 사용자 정의함수라고 합니다. 이를 작성하는 것은 사용자가 R을 더 효율적으로, 기능적으로, 그리고 생산적인 통계분석처리를 할 수 있도록 도와줍니다.

mean(), var(), postscript()와 같이 R시스템에 미리 내장된 많은 함수들 역시 R로 쓰여졌기 때문에, 대다수의 내장함수들이 사용자 정의함수라고 할 수도 있습니다.

다음은 함수를 정의하는 방법입니다.

> name <- function(arg_1, arg_2, …) expression

여기에서 expression 이란 어떤 값을 계산하기 위해 사용되는 arg_i를 이용하여 작성되는 R표현식 (일반적으로 그룹화된 표현식)입니다.

그리고, expression을 수행함으로 얻어진 최종적인 결과를 함수의 반환값이라고 합니다.이렇게 정의된 함수를 사용하는 방법은 어느 곳에서나 name(expr_1, expr_2, …)이라고 사용하면 됩니다.


10.1 간단한 예제

첫번째 예제를 살펴봅니다. 두개의 샘플로부터 t-통계량을 구하는 함수를 다음과 같이 정의할 수 있습니다.

The function is defined as follows:

> twosam <- function(y1, y2) {
    n1  <- length(y1); n2  <- length(y2)
    yb1 <- mean(y1);   yb2 <- mean(y2)
    s1  <- var(y1);    s2  <- var(y2)
    s <- ((n1-1)*s1 + (n2-1)*s2)/(n1+n2-2)
    tst <- (yb1 - yb2)/sqrt(s*(1/n1 + 1/n2))
    tst
  }

이렇게 함수를 정의한 뒤, 이 정의한 함수 twosam을 아래와 같은 방법으로 사용할 수 있습니다.

> tstat <- twosam(data$male, data$female); tstat

두번째 예제는 MATLAB에서 최소제곱법을 이용하여 회귀모델의 회귀계수를 구해주는 백슬래쉬(backslash)라는 명령어를 구현해보는 것입니다.본래 이것은 qr()함수를 이용하여 할 수도 있으나, 어떤 경우에는 직접적으로 활용하기가 곤란한 경우가 있습니다. 따라서, 다음과 같은 방식을 사용하는 것을 권장합니다.

만약, n개의 원소를 가지는 열벡터 y가 있고, 사이즈가 np열을 가진 디자인행렬 X가 있다면 X\y는 (X’X)^{-}X’y, where (X’X)^{-} 로 정의할 수 있으며, (X'X)^{-}X'X의 역행렬입니다.

> bslash <- function(X, y) {
  X <- qr(X)
  qr.coef(X, y)
}

위와 같이 정의된 bslahs 함수는 아래와 같이 regcoeff라는 객체에 결과를 저장하게 됩니다.

> regcoeff <- bslash(Xmat, yvar)

and so on.

이러한 기능은 R에서 제공하는 lsfit() 함수를 통하여 더 잘 수행될 수 있습니다.20. 실제로, qr()qr.coef()의 사용은 회귀계수를 구하는데 있어서 직관적이라고 보기 어려우며, 사용에 번거롭기도 합니다. 보다 편리한 사용을 위해 사용자가 직접 정의하는 이항연산자(binary operator)라는 기능을 제공합니다.


10.2 새로운 이항연산자를 정의하기

위에서 bslash() 함수를 작성하였습니다. 그러나 이러한 연산의 수행은 함수를 작성하는 것보다 아래와 같은 연산자의 형태를 지닌다면 훨씬 편리할 것입니다.

%anything%

예를 들어, anything이라는 부분에 느낌표(!)를 이용하여 %!%이라는 새로운 이항연산자를 아래와 같이 큰 따옴표를 이용하여 정의할 수 있습니다.

> "%!%" <- function(X, y) { … }

이렇게 새로이 정의된 연산자는 X %!% y와 같이 사용할 수 있습니다.

행렬의 곱셈을 수행하는 연산자 %*%, 외적을 수행하는 연산자 %o%는 이러한 방법으로 정의된 이항연산자의 대표적인 경우입니다.


10.3 인자명과 기본값

Generating regular sequences (규칙성을 지닌 일련의 숫자들을 생성하기)에서 설명했던 것과 같이 함수에 사용되는 인자들은 “name=object”와 같은 형식을 가지고 있습니다.이러한 방식으로 함수의 정의시 인자의 이름을 굳이 함께 정의하는 것은 프로그래밍의 논리적 오류를 줄이고자 하는 노력이라고 보시길 바랍니다.

예를들어, 아래와 같이 정의된 함수 fun1가 있다고 가정한다면,

> fun1 <- function(data, data.frame, graph, limit) {
    [function body omitted]
  }

아래와 같이 세가지 방법으로 사용이 가능하며, 모두 같은 결과를 줍니다.

> ans <- fun1(d, df, TRUE, 20)
> ans <- fun1(d, df, graph=TRUE, limit=20)
> ans <- fun1(data=d, limit=20, graph=TRUE, data.frame=df)

are all equivalent.

그런데, R에서 제공하는 모든 함수들은 아래에서 보여지는 것과 같이 함수의 인자에 기본값이라는 것이 부여되어 있음을 알 수 있습니다.

> fun1 <- function(data, data.frame, graph=TRUE, limit=20) { … }

따라서, 이 기본값들을 이용하여 함수의 모든 인자를 입력하지 않아도 함수는 연산을 수행하게 됩니다.아래와 같은 사용은 위의 세가지 다른 방법으로 사용했던것과 동일한 결과를 줍니다.

> ans <- fun1(d, df)

limit의 기본값을 20에서 10으로 바꾸어 실행하고자 한다면 아래와 같이 할 수 있습니다.

> ans <- fun1(d, df, limit=10)

which changes one of the defaults.

인자에 주어지는 기본값들이 본 예제에서 사용된 것과 같이 상수일 필요는 없으며, 임의의 표현식이 될 수 있습니다.


10.4 The ‘’ argument

함수를 정의할 때 ‘’라는 표현을 알아두면 매우 유용합니다.이는 한 함수의 인자들에 대한 설정을 다른 함수로 넘겨주는 것을 허용하는 역할을 합니다.예를들어, plot()과 같은 그래픽 함수들은 그래픽의 결과물을 정교히 조정하기 위한 방대한 양의 인자들이 포함하고 있는 함수 par()를 사용합니다. par()에 대해서 자세히 알고 싶으시다면 See The par() function를 살펴보시길 바랍니다.

fun1 <- function(data, data.frame, graph=TRUE, limit=20, ...) {
  [omitted statements]
  if (graph)
    par(pch="*", ...)
  [more omissions]
}

따라서, 그래픽 함수들은 실제로는 par()라는 함수에 있는 인자를 사용함으로서 결과물의 수정 및 조정을 조정하고, 이러한 역할을 위한 인자를 따로 정의하고 있지 않습니다. 이렇게 외부에 정의에 되어 있는 함수 및 객체들의 인자들을 정의하고자 하는 함수로 불러들여와 활용하고자할 때, 아래의 코드에서 보이는 것과 같이 ‘’를 함수 선언부에 나열된 인자들의 목록뒤에 붙여주면 됩니다.


10.5 Assignments within functions

함수 내부에서 이루어진 값에 대한 모든 할당은 함수내부내에서만 유효합니다. 따라서, X <- qr(X)은 호출하는 프로그램에 있는 인자들의 값에 아무런 영향을 미치지 않습니다.이렇게 변수가 가지는 값이 지정된 함수 내부에서만 사용되는것을 지역할당(local assignment) 이라고 합니다.

R시스템내에서 할당범위 (the scope of assignment)에 대한 규칙들을 이해하기 위해서는 프레임(frame)이 어떻게 평가가 되는지에 대한 개념에 익숙해져야만 합니다.그러나, 이것은 이 안내서의 수준을 벗어나므로 설명하지 않겠습니다.

만약, 함수 내부에서 연산된 어떤 값을 함수 외부 및 작성하는 프로그램 전체에서 사용하고 싶다면, 슈퍼할당 (superassignment)이라는 연산자 <<-를 사용하거나, 함수 assign()를 이용하시길 바랍니다.이렇게 변수가 가지는 값이 특정 함수내에서 국한되지 않고 전체에서 활용되는 개념을 전역할당 (global assignment 혹은 permanent assignment) 라고 합니다. 이것에 대한 더 자세한 사항은 도움말 help을 참조하시길 바랍니다. S-PLUS사용자는 <<- 연산자가 R에서 다른 의미로 사용된다는 점을 반드시 알고 있어야 합니다. 이러한 다른 점들은 Scope (스코프)에서 다루어질 것입니다.


10.6 좀 더 발전된 예제들


10.6.1 Efficiency factors in block designs

함수에 대해서 좀 더 자세히 다루기 위해서 이번에는 블락 디자인에서 사용되는 효율성요인(efficiency factor)을 찾아보도록 하겠습니다. 이 문제에 대한 일부 내용은 이미 Index matrices (인덱스 행렬)에서 다룬바 있습니다.

b수준을 가진 요인 blocksv수준을 가진 요인 varieties을 이용한 블락 디자인을 생각해 봅니다.그리고, RK가 각각 vv열인 행렬 replicationsbb열인 행렬 block size이라고 합니다.효율성요인(efficiency factor)은 아래와 같은 행렬의 기저값(eigenvalues)을 이용하여, 구할 수 있습니다. E = I_v - R^{-1/2}N’K^{-1}NR^{-1/2} = I_v - A’A, where A = K^{-1/2}NR^{-1/2}. 다음은 이를 산출하는 함수를 작성한 것입니다.

> bdeff <- function(blocks, varieties) {
    blocks <- as.factor(blocks)             # minor safety move
    b <- length(levels(blocks))
    varieties <- as.factor(varieties)       # minor safety move
    v <- length(levels(varieties))
    K <- as.vector(table(blocks))           # remove dim attr
    R <- as.vector(table(varieties))        # remove dim attr
    N <- table(blocks, varieties)
    A <- 1/sqrt(K) * N * rep(1/sqrt(R), rep(b, v))
    sv <- svd(A)
    list(eff=1 - sv$d^2, blockcv=sv$u, varietycv=sv$v)
}

실제로 이경우에는 the singular value decomposition을 이용하는 것이 기저값(eigenvalue)를 이용한 방법보다 보다 나은 연산결과를 줍니다.

위에서 작성된 함수는 효율성 요인만을 결과값으로 돌려주는 것만이 아니라 blockvariety 정준대비(canonical contrast) 또한 알려줍니다. 그 이유는 이 두가지 결과값들이 때때로 유용하기 때문입니다.


10.6.2 Dropping all names in a printed array

사이즈가 큰 행렬 혹은 배열의 출력이 주목적인 경우, 행렬과 배열의 구성요소의 위치를 알려주는 행, 열, 혹은 차원에 대한 정보를 나타내지 않고 오로지 데이터값만을 출력하는 것이 유용한 경우가 있습니다. 이런 경우에는 속성 dimnames이 가지는 문자열값들을 초기화 시켜주면 됩니다. 예를 들어 행렬 X의 행과 열의 정보 없이 데이터만 출력하고자 할 경우, 아래와 같이 할 수 있습니다.

> temp <- X
> dimnames(temp) <- list(rep("", nrow(X)), rep("", ncol(X)))
> temp; rm(temp)

이와 같은 기능을 아래와 같이 no.dimnames()라는 사용자정의 함수를 작성함으로서 수행할 수 도 있습니다. 이것은 또한 이렇게 유용한 기능을 위한 사용자정의함수가 꼭 길지 않아도 됨을 잘 보여주고 있습니다.

no.dimnames <- function(a) {
  ## Remove all dimension names from an array for compact printing.
  d <- list()
  l <- 0
  for(i in dim(a)) {
    d[[l <- l + 1]] <- rep("", i)
  }
  dimnames(a) <- d
  a
}

위와 같이 정의된 함수는 아래와 같이 사용함으로서 배열이 가지는 데이터 값들만 출력해낼수 있습니다.

> no.dimnames(X)

이번 섹션에서 다룬 내용은 배열 데이터 값 자체 보다 배열의 값들이 가지는 패턴을 분석하고자 할때 더 유용하므로 주로 사이즈가 큰 정수형 배열을 다룰때 사용됩니다


10.6.3 Recursive numerical integration

함수는 재귀적일 수 있으며, 함수 자신이 함수 자신내에 함수를 정의할 수도 있습니다.그러나, 이러한 함수들 (또는 실제로 변수들)은 마치 탐색경로(serach path)에 존재했던 것같은 상위평가프레임 (higer evaluation frames)내에서 불려진 함수에 의해 존재하는 것이 아니라는 점을 알고 있어야 합니다.

아래의 예제는 1개의 변수만을 가지는 함수를 적분하는 기초적인 방법에 대해서 다루고 있습니다. 적분을 하는 기본 개념은 먼저 적분하고자 하는 범위의 양쪽 끝점과 그 중간점에 해당하는 함수들의 값을 얻어낸 후, 사다리꼴 공식을 이용하여 단일 패널에서 얻어진 결과가 이중패널에서 얻어진 결과와 매우 유사할 경우 이중패널로부터 얻어진 결과를 적분값으로 결정합니다. 만약, 그렇지 않다면 각각의 패널에 위에서 묘사한 프로세스를 다시 적용하되 값의 변화가 없을때까지 반복합니다.

이 예제는 R 프로그래밍을 하는데 있어서 다소 복잡한 부분에 해당하므로 이해가 어려울 수 도 있습니다.

area <- function(f, a, b, eps = 1.0e-06, lim = 10) {
  fun1 <- function(f, a, b, fa, fb, a0, eps, lim, fun) {
    ## function ‘fun1’ is only visible inside ‘area’
    d <- (a + b)/2
    h <- (b - a)/4
    fd <- f(d)
    a1 <- h * (fa + fd)
    a2 <- h * (fd + fb)
    if(abs(a0 - a1 - a2) < eps || lim == 0)
      return(a1 + a2)
    else {
      return(fun(f, a, d, fa, fd, a1, eps, lim - 1, fun) +
             fun(f, d, b, fd, fb, a2, eps, lim - 1, fun))
    }
  }
  fa <- f(a)
  fb <- f(b)
  a0 <- ((fa + fb) * (b - a))/2
  fun1(f, a, b, fa, fb, a0, eps, lim, fun1)
}

10.7 Scope (스코프)

이번 섹션에서 다루어질 내용은 이 문서의 다른 부분들보다는 다소 어려운 기술적인 부분에 해당합니다. 그러나, 이 부분은 R과 S-PLUS간의 다른 점들 중 함수와 관련된 부분입니다.

먼저 함수의 본체에 사용되는 기호는 형식인자 (formal parameters), 지역변수 (local variables), 그리고 자유변수 (free variables) 라는 세가지가 있습니다.형식인자 (formal parameters)라는 것은 함수 선언시 아직 값이 부여되지 않은 인자들의 목록을 의미합니다. 따라서 형식인자 (formal parameters)는 실제로 함수가 사용될 때 함수가 받아들이는 인자의 값을 가지게 됩니다. 이에 반해, 지역변수라는 것은 함수 본체에서 사용된 표현식의 결과값들을 가지게 됩니다. 만약, 어떤 변수가 형식인자 (formal parameters)도 아니고 지역변수도 아닌 경우, 이러한 변수를 바로 자유변수라고 합니다. 그러나, 상황에 따라서 자유변수에 값이 부여될 경우 이는 지역변수가 되기도 합니다. 더 정확한 개념의 이해를 위해서 다음의 예제를 살펴봅시다.

f <- function(x) {
  y <- 2*x
  print(x)
  print(y)
  print(z)
}

여기 정의되어 있는 함수 fx라는 형식인자 (formal parameter)를 가지며, y라는 지역변수를 가지는데 반해, 자유변수 z를 가지고 있습니다.

R에서 자유변수에 대한 값의 할당은 변수가 관리가 되고 있는 함수에 우선권이 부여되며, 이것을 렉시컬 스코프 (lexical scope)라고 합니다. 이해를 돕기 위해서 아래와 같이 정의된 함수 cube를 살펴봅니다.

cube <- function(n) {
  sq <- function() n*n
  n*sq()
}

함수 sq내에 있는 변수 n은 형식인자가 아닌 자유변수입니다. 이 자유변수가 어떠한 값을 가져야 하는가에 대해서 스코핑 규칙 (scoping rules)이 적용됩니다. 정적 스코핑 규칙(static scoping rule)을 가지는 S-PLUS에서는 자유변수가 가지는 값은 n이라는 이름을 가진 전역변수 (global variable)에 의해서 그 값이 결정됩니다. 이에 반해, 렉시컬 스코핑 규칙을 가지는 R은 자유변수에 함수 cube라는 실행될 때 가지는 인자의 값을 할당 합니다. 그 이유는 n은 함수 sq가 정의되기 ’바로 이전에’ 함수 cube 내부에서 정의되어 관리되는 변수이기 때문입니다. 이러한 스코핑 규칙의 차이는 R과 S-PLUS를 구분짓는 큰 특징들 중의 하나 입니다. 즉, R의 기본적인 스코핑 규칙은 전역변수에 의한 관리가 아닌 지역에 촛점을 맞춘 렉시컬 스코핑을 따르는 것입니다.

## first evaluation in S
S> cube(2)
Error in sq(): Object "n" not found
Dumped
S> n <- 3
S> cube(2)
[1] 18
## then the same function evaluated in R
R> cube(2)
[1] 8

다음의 예제는 R의 렉시컬 스코핑이 얼마나 효율적으로 은행계좌를 구현할 수 있는가를 보여줍니다. 은행계좌를 구현하기 위해서는 총계 (balance 혹은 total), 출금 (withdrawal), 입금 (deposits), 그리고 현재잔고(current balance)이 필요합니다. 먼저, 출급, 입금, 그리고 잔고에 대한 함수를 먼저 만든 뒤, 이를 리스트형식으로 한데 묶어 함수 account를 정의합니다. 함수 account가 실제적으로 실행되었을때 total이라는 인자는 특정한 값을 가진 인자가 되어 리스트에 정의되어 있는 출금, 입금, 그리고 잔고라는 함수에 그 값을 전달하게 됩니다. 그 이유는 바로 total이라는 인자가 함수 account에 의해서 정의되어 관리되는 변수이기 때문입니다.

The special assignment operator, <<-, 아래에서 보이는 것과 같이 total이라는 변수의 값을 변경하기 위해서 특별한 할당 연산자인 <<-를 사용하였습니다.이 연산자는 기호 total이 존재하는 환경(environment)을 둘러싼 환경 (enclosing enviornment)을 살펴보고, 그러한 환경이 찾아졌을때 해당 환경에 존재하는 값으로 대체하게 됩니다. 만약, 기호 total을 프로그램 전역 또는 최상위 환경 (top-level environment)에 도달할때까지도 찾을 수 없었다면, 기호 total이 새로이 생성이 되고 그 값이 할당되게 됩니다.21

open.account <- function(total) {
  list(
    deposit = function(amount) {
      if(amount <= 0)
        stop("Deposits must be positive!\n")
      total <<- total + amount
      cat(amount, "deposited.  Your balance is", total, "\n\n")
    },
    withdraw = function(amount) {
      if(amount > total)
        stop("You don't have that much money!\n")
      total <<- total - amount
      cat(amount, "withdrawn.  Your balance is", total, "\n\n")
    },
    balance = function() {
      cat("Your balance is", total, "\n\n")
    }
  )
}

ross <- open.account(100)
robert <- open.account(200)

ross$withdraw(30)
ross$balance()
robert$balance()

ross$deposit(50)
ross$balance()
ross$withdraw(500)

10.8 환경 설정하기

사용자는 사용자의 환경설정을 여러가지 방법으로 변경할 수 있습니다.먼저, 사이트 초기화 파일(site initialization file)이라는 것이 있고, 각각의 디렉토리마다 특정역할을 하는 초기화 파일(special initialization file)이 있습니다. 그리고, .First.Last이라는 특수한 함수들이 있습니다.

사이트 초기화 파일의 위치는 R_PROFILE이라는 환경변수의 값에 의해 정해집니다. 만약, 이 환경변수의 값이 정해지지 않았다면 R의 홈에 있는 etc라는 하위디렉토리에 있는 Rprofile.site의 값이 사용되게 됩니다.이 파일은 사용자의 시스템에서 R이 실행될때마다 반드시 실행되어야 할 명령어들을 포함하고 있습니다.두번째로 .Rprofile22이라는 개인프로파일이라는 파일은 어느 디렉토리에나 놓일 수 있습니다.만약, R이 해당 디렉토리에서 실행된다면 이 파일은 소스될(sourced, 즉 불러들어 읽힘) 것입니다.이 파일은 해당 작업공간에 대한 개인사용자 설정이며, 다른 디렉토리마다 다른 스타트업(startup) 절차를 수행할 수 있게 해줍니다.만약, .Rprofile이라는 파일을 스타트업 디렉토리에 없다면, R은 사용자의 홈디렉토리에 있는 (만약 있다면) .Rprofile을 사용하게 됩니다.만약, 환경설정변수 R_PROFILE_USER가 지정되어 있다면, .Rprofile파일대신에 사용될 것입니다.

사이트 프로파일, 사용자 프로파일, 그리고 .RData라는 이미지 내부에 .First()라고 이름이 붙은 함수들은 특정한 상태를 가지고 있습니다. 이것들은 R세션이 시작할 때 자동으로 작업환경을 초기화할 때 사용되게 됩니다. 아래의 코드를 살펴 보신다면 더 빠른 이해를 가지실 수 있습니다. 예를들어, 함수 .First의 정의중 prompt라는 인자 $를 다른 기호로 변경하여 R세션내내 사용자가 변경한 기호로 프롬프트를 사용할 수 있습니다.

일반적으로 사용자의 환경설정을 위한 파일의 실행순서는 Rprofiles.site, 그리고 사용자 프로파일, .RData, 그리고 .First() 순입니다.

> .First <- function() {
  options(prompt="$ ", continue="+\t")  # $ is the prompt
  options(digits=5, length=999)         # custom numbers and printout
  x11()                                 # for graphics
  par(pch = "+")                        # plotting character
  source(file.path(Sys.getenv("HOME"), "R", "mystuff.R"))
                                        # my personal functions
  library(MASS)                         # attach a package
}

위에서 정의된 .First()와 유사하게 함수 .Last()를 아래와 같이 정의할 수 있습니다.이는 보통 세션 종료시 사용됩니다.

> .Last <- function() {
  graphics.off()                        # a small safety measure.
  cat(paste(date(),"\nAdios\n"))        # Is it time for lunch?
}

10.9 클래스, 제네릭 함수, 그리고 객체지향 프로그래밍

객체의 클래스라는 것은 제네릭 함수 (generic function)가 어떻게 그 객체를 처리할 것인지 대한 정보를 제공합니다. 즉, 제네릭 함수라는 것은 객체의 클래스정보를 인자로 가지기 때문에 만약 클래스 정보가 없거나, 제네릭 함수내에서 해당 클래스에 대한 처리방법이 정의되지 않았다면 기본행동 (default action)을 수행하게 됩니다.

예를 들면 더욱 수월하게 이해가 가실 것입니다.클래스 메커니즘 (작동하는 방법)은 사용자가 제네릭 함수를 디자인하고 새로 정의할 수 있도록 도와줍니다. 단편적인 예로 plot()이라는 제네릭 함수는 여러가지 객체의 종류 (즉, 클래스)에 따른 다양한 시각화 방법을 제공합니다.또 다른 제네릭함수 summary()는 다양한 종류의 객체에 대한 통계분석의 결과를 요약해 주며, anova()는 여러개의 통계 모델들을 비교할 때 사용됩니다.

클래스를 특정한 방법으로 처리하는 제네릭 함수의 수는 매우 많습니다. 예를 들어, 클래스 "data.frame"의 객체를 처리하는 방법들에 대해서는 아래와 같은 내용들이 있습니다.

[     [[<-    any    as.matrix
[<-   mean    plot   summary

이와 같이 어떤 처리 방법들이 제네릭 함수안에 구현이 되어 있는지 확인하고 싶다면 아래와 같이 methods()를 사용해보세요.

> methods(class="data.frame")

이와 반대로, 제네릭 함수가 처리해 낼 수 있는 클래스의 종류 또한 많습니다. 예를 들어, 함수 plot()는 기본처리방법(default method)을 가지고 있고, "data.frame", "density", "factor", 그 밖의 클래스들로부터 파생되어진 다양한 종류의 객체들을 처리할 수 있습니다. 만약, 어떠한 종류의 객체들을 처리할 수 있는지 확인해 보고 싶으시다면 아래와 같이 methods()를 함수의 이름과 함께 사용하시면 됩니다.

> methods(plot)

일반적으로 제네릭 함수의 본체는 아래에서 보는 것과 같이 매우 짧습니다.

> coef
function (object, ...)
UseMethod("coef")

여기에서 UseMethod라는 coef라는 함수가 제네릭 함수임을 의미하는 것입니다.따라서 coef라는 제네릭 함수에 대한 처리방식에 대한 내용을 확인하고 싶으시다면 methods()를 사용하시면 됩니다.

> methods(coef)
[1] coef.aov*         coef.Arima*       coef.default*     coef.listof*
[5] coef.nls*         coef.summary.nls*

   Non-visible functions are asterisked

위의 예제는 6가지의 처리방식이 있으나, 위에서 보는 바와 같이 메소드들이 어떻게 작성되었는지에 대해서는 보여지지 않는다고 *를 이용하여 표기하고 있습니다. 그러나, 아래와 같은 방법으로 이러한 메소드들에 대한 알고리즘의 구현방법을 확인할 수 있습니다.

> getAnywhere("coef.aov")
A single object matching 'coef.aov' was found
It was found in the following places
  registered S3 method for coef from namespace stats
  namespace:stats
with value

function (object, ...)
{
    z <- object$coef
    z[!is.na(z)]
}

> getS3method("coef", "aov")
function (object, ...)
{
    z <- object$coef
    z[!is.na(z)]
}

A function named gen.cl will be invoked by the generic gen for class cl, so do not name functions in this style unless they are intended to be methods.

이 섹션의 내용을 더 정확히 이해하기 위해서는 R Language Definition라는 문서를 참고하셔야 합니다.


11 Statistical models in R (R에서 사용되는 통계모형들)

이번 섹션에서 다루게 될 내용은 여러분이 이미 회귀분석(regression analysis)이나 분산분석(analysis of variance)등에 대해서 어느 정도 알고 있다고 가정한 상태에서 작성한 것입니다. 그리고, 후반부에서는 조금 더 욕심을 내서 일반화 선형 모형(generalised linear model)과 비선형 모형(nonlinear model)과 같은 내용에 대해서도 어느 정도 알고 계실거라고 가정하겠습니다.

R은 다양한 통계모형을 매우 간단하게 적합시킬 수 있도록 해주는 여러 도구들을 완벽하게 조합해놓은 종합 도구 상자같은 것입니다.

본 문서의 서두에서 언급했던 것 처럼, R은 분석 수행시 최소한의 결과물만을 출력하기 때문에 중간절차에 대한 상세한 내용을 확인하기 위해서는 추출계열의 함수(extractor functions)들을 사용하셔야 합니다.


11.1 Defining statistical models; formulae

일반적인 통계모형의 템플릿(template)이라고 하면 독립(independent)이고 등분산(homoscedastic)인 오차(errors)를 가정하는 선형 회귀 모형을 떠올릴 것 입니다. 선형 회귀모형(linear regression model)은 보통 다음과 같이 표현됩니다.하나의 모형에는 p개의 설명변수가 있고, 이들은 j라는 첨자를 사용해서 구분합니다.따라서, x_jj번째 설명변수를 의미합니다. 또한, n개의 관측으로 데이터를 구성하며, 각 관측은 첨자 i로 구분합니다.따라서, y_ii번째 관측으로부터 얻은 종속변수의 값을 의미합니다.마지막으로 e_i를 사용해서 i번째 관측의 오차항을 표현합니다.이 식에서 오차항은 e_i은 IID(Independently, Identically Distributed/독립이며 같은 분포를 따르는)인 평균이 0이고 분산이 sigma^2인 정규(Normal)분포를 따릅니다. 여기서 독립이란 i번째 관측치와 i번째가 아닌 다른 관측치 사이에 아무런 관련이 없으며, 개별 관측이 따로 얻어졌다는 것을 의미합니다.

y_i = sum_{j=0}^p beta_j x_{ij} + e_i,     i = 1, …, n,

where the e_i are NID(0, sigma^2). 위의 식은 행렬 형태로 아래와 같이 표현되며,

y = X  beta + e

y는 종속변수 벡터, 설명변수들로 구성된 X모형 행렬(model matrix) 또는 디자인 행렬(design matrix)이라고 불리며, 설명변수(또는 열)들을 x_0, x_1, …, x_p의 형태로 포함합니다. 종종 x_0라는 1로만 구성된 열 하나가 여기에 더 추가되는데, 이는 절편(intercept)을 정의하기 위해서 사용된 것입니다.

Examples

본격적으로 회귀모형의 사용을 다루기 전, 몇 가지 예제를 통해 이해를 돕도록 하겠습니다.

먼저 y, x, x0, x1, x2, …는 모두 수치형 벡터, X는 행렬, 그리고 A, B, C, …는 요인들을 나타낸다고 가정합니다.아래에서 우리가 살펴보고자 하는 통계 모형들은 왼편에 식으로 표기되어 있고, 그 아래는 해당 모형에 대한 설명이 제시되어 있습니다.

y ~ x
y ~ 1 + x

이 두가지 식은 모두 같은 모형을 나타내고 있으며, yx에 회귀시킨 단순 선형 회귀모형 (simple linear regression model)을 의미합니다.여기에서 "단순(simple)"이라는 말은 모형에 포함된 설명변수가 1개임을 의미합니다.첫번째 식은 절편을 따로 표시하지 않았지만, 두번째 식은 절편을 따로 표시한 것 입니다.(절편항에 대해 따로 명시하지 않으면, R에서는 디폴트(default)로 디자인 행렬에 절편항을 포함시킵니다.)

y ~ 0 + x
y ~ -1 + x
y ~ x - 1

위 세 식은 원점(origin)을 지나는 yx에 회귀시킨 단순 선형 회귀모형을 의미합니다. (즉, 이는 절편을 포함하지 않는 회귀모형 입니다.)

log(y) ~ x1 + x2

로 변환된 y를 두 개의 설명변수인 x1x2에 회귀시킨 다중회귀모델 (multiple regression)입니다. (표시되지 않았지만 절편을 포함하는 모형입니다.) log(y), on x1 and x2 (with an implicit intercept term).

y ~ poly(x,2)
y ~ 1 + x + I(x^2)

위 식들은 yx의 이차항에 회귀시킨 다차항 회귀(polynomial regression)모형 입니다. x의 이차항이라는 것은 x^2를 의미하는 것으로, 첫번째 식은 직교다차항(orthogonal polynomials)을,두번째 식은 x의 0차, 1차, 2차항인 x^0, x^1, x^2를 베이시스(basis)로 사용하는 모형임을 표현하는 것 입니다.

y ~ X + poly(x,2)

위 식은 행렬인 Xx의 2차항으로 구성된 다중 회귀모형을 의미합니다.

y ~ A

위 식은 y에 대한 요인 A와 공변량(covariate) x의 단순(single) 공분산분석(classification analysis of covariance/ANCOVA)를 의미합니다. 여기서 A의 수준이 y를 분석하기 위한 클래스(class)를 결정합니다. 23

y ~ A + x

Single classification analysis of covariance model of y, with classes determined by A, and with covariate x.

y ~ A*B
y ~ A + B + A:B
y ~ B %in% A
y ~ A/B

위 식은 모두 y를 두 개의 요인 AB로 설명하는 이원배치(Two factor) 비가산(non-additive) 모형을 표현하고 있습니다. 처음 두 식은 모두 (교호작용(interaction)항을 포함하는) 이원배치 혼합모형(crossed classification)을 나타내며, 다음의 두 식은 모두 중첩모형 (nested classification)을 나타냅니다. 하지만, 현대 대수학(abstract algebra)식으로 말하면, 네 가지 모형은 모두 같은 모형 서브스페이스(subspace)를 표현합니다.

y ~ (A + B + C)^2
y ~ A*B*C - A:B:C

위의 식은 모두 삼원배치(three factor) 실험을 표현하고 있지만,주효과(main effect/일차원 효과)와 두개 요인간의 교호작용(interaction)들만 포함하는 모형입니다. 두 식은 모두 같은 모형을 표현합니다.

y ~ A * x
y ~ A/x
y ~ A/(1 + x) - 1

위의 세 식은 요인 A의 각 수준 별로 yx에 회귀시켜 여러개의 단순 선형 회귀모형(simple linear regression)을 동시에 적합시키는 방법을 다른 코딩 방식으로 표현한 것입니다. 특히, 마지막 식을 사용할 경우,A의 수준의 개수만큼 서로 다른 절편(intercept)과 기울기(slope)의 추정치(estimate)가 계산됩니다.

y ~ A*B + Error(C)

위 식은 두 개의 처리 요인 AB를 갖는 실험을 나타내며, 이 모형의 오차는 요인 C의 수준 별로 계층화(strata)되어 있습니다. (역주-이 경우, 좀 더 전문적인 용어로 표현하면 오차가 요인 C에 의해 블록(block)화 된것이라 볼 수 있으며, 일종의 랜덤효과(random effects)로 가정된 것 입니다. 이렇게 처리 요인과 블록화된 요인을 모두 포함하는 실험은 혼합모형(mixed model)을 사용하여 분석할 수 있습니다.)

R에서 모델식(model formula)을 정의할 때는 ~(틸다) 연산자를 사용한 것을 확인하실 수 있을 것 입니다. (이 연산자는 식의 왼쪽과 오른쪽을 연결시키는 역할을 하며, 이러한 사용은 수학에서 식의 오른쪽과 왼쪽이 완전하게 동일하다는 의미를 나타내는 등호 (=)를 사용하는 것과는 다릅니다. 예를 들면, 간단한 일반(ordinary) 선형모형은 다음과 같이 정의할 수 있습니다.

response ~ op_1 term_1 op_2 term_2 op_3 term_3 

where

response

는 하나의 벡터 또는 행렬(경우에 따라서는 벡터나 행렬로 결과를 출력할 표현식)이 될 수 있습니다.

op_i

+ 또는 - 부호를 갖는 연산자로, 각각 모형식에서 i 번째 변수를 추가하거나 제거하기 위해 사용합니다. (식의 가장 처음에 오는 (첫번째 항을 받는) 연산자는 굳이 사용하지 않아도 됩니다.)

term_i (i 번째 항)
term_i

으로는 다음의 중 한가지가 가능합니다:

모형이 이런식으로 표현될 경우, 식에 포함되는 각 항은 모형행렬(model matrix)을 구성하는 각 열이 모형에서 추가될질지 혹은 제거될지를 나타내기위해 사용됩니다.위에서 1이라는 항은 회귀식에서 절편을 나타내기 위해 사용되었으며, 따로 이 항을 생략하기 위한 표현식을 사용하지 않는 한, 항상 디폴트(default)로 모형행렬에 포함됩니다.

식 연산자(formula operator)는 Glim 이나 Genstat 같은 프로그램에서 사용되는 Wilkinson과 Rogers의 표기법(notation) 과 거의 비슷하게 정의 되었습니다.한 가지 눈에 띄는 차이가 있다면, GLIM이나 Genstat에서는 ‘.’에 해당하는 연산자를 R에서는 ‘:’ 연산자로 사용하고 있다는 점 일 것입니다. 이렇게 된 이유는 ‘.’ 기호가 R에서는 변수이름으로 사용할 수 있는 문자 중 하나이기 때문입니다.

이 표기법(notation)에 대해서는 Chambers & Hastie (1991, p.29)를 바탕으로 다음과 같이 요약해 볼 수 있습니다:

앞서 설명드린 것 처럼 ~(틸다) 연산자는 Y를 모형식(model formula)을 의미하는 M 부분과 연결시켜 줍니다.

앞서 설명드린 것 처럼 ~(틸다) 연산자는 Y를 모형식(model formula)을 의미하는 M 부분과 연결시켜 줍니다.

M_1 + M_2

M_1M_2과 모두 모형에 포함합니다.

M_1 - M_2

M_1은 모형에 포함되지만 M_2 부분은 모형에서 제외합니다.

M_1 : M_2

M_1M_2를 텐서곱(tensor product) 합니다.만약, 두 개의 항 모두 요인이라면 tensor product의 결과는 M_1M_2가 갖는 모든 수준(level)들의 조합으로 생성된 모든 서브클래스(“subclasses”)가 됩니다.

M_1 %in% M_2

M_1:M_2와 비슷한 작업을 수행하는 다른 코딩 방법입니다.

M_1 * M_2

M_1 + M_2 + M_1:M_2.

M_1 / M_2

M_1 + M_2 %in% M_1.

M^n

n차항까지의 M에 포함된 모든 항들과 이들간의 모든 교호작용(“interactions”)을 의미합니다.

I(M)

I() 연산자는 insulate((식을) 보호함, 최근 버전에서는 Inhibit/(연산을)억제함으로 표현하기도 함)의 약자로서 모형식(model formula)에서, M에 작성된 표현식을 그 산술적(arithmetic) 의미대로 실행하여 그 결과가 모형행렬(model matrix)에서 하나의 항으로 포함될 수 있도록 해줍니다.

일반적으로 R에서는 M의 표현식에 포함된 모든 연산자들이 원래의 산술적 의미 그대로 사용됩니다. 하지만 모형연산자(model operators)로 사용되는 + 혹은 - 연산자는 해당 변수를 모델식(model formula)에 포함할 것인지 제외할 것인지를 의미합니다. 하지만, 함수 I()는 일종의 아이덴티티(identity) 함수로 이 함수가 쓰인 해당 항이 모형식(model formulae) 내에서 산술 연산자를 포함할 수 있도록 해줍니다. 따라서, 모형식 안에서I(M_1+M_2)를 사용하면, M_1M_2을 더해진 결과가 하나의 항으로 식에 포함됩니다.

모형식(model formula)을 정의하는 데 있어, 모형행렬(model matrix)의 열을 선택하는 것은 내재적으로 모형의 모수(parameters)를 선택하는 과정이기도 합니다. 하지만, 이런 내재적 의미는, 비선형(nonlinear)모형을 적합하는 것과 같은 다른 상황(context)에서는 성립하지 않는다는 점을 알아두시기 바랍니다.


11.1.1 Contrasts

이 부분에서는 최소한 모형식(model formula)을 지정하는 것이 모형 행렬(model matrix)의 열을 선택하는 것과 어떤 관련이 있는지 정도는 알고 있다고 가정하고 내용을 진행하겠습니다. 연속형 변수들이 각각의 열을 구성하는 모형 행렬(model matrix)을 생각해보면 (사용할 모형이 절편(intercept)를 포함할 경우, 이 행렬은 1로만 이루어진 열을 하나 더 포함할 것입니다.), 이 관계를 이해하는 것이 전혀 어렵지 않을 것 입니다.

그러나, k-개의 수준(level)을 가진 요인 A이 모형에 포함된다고 가정하면, 이 요인이 순서형(ordered)인지 비순서형(unordered)인지에 따라 이 관계가 조금 달라지게 됩니다.우선 비순서형 요인(unordered factor)의 경우, 두번째 수준부터 마지막 k번째 수준에 각각 대응되는 인디케이터(indicator/더미(dummy)변수)를 나타내기 위해 k -1 개의 열이 생성됩니다.(따라서, 이러한 모형화(parametrization)는 암묵적으로 각 수준이 첫번째 수준과 대조(contrast)시킵니다). 이와는 다르게, 순서형 요인(ordered factor)의 경우, k-1개의 열들은 상수항을 제외한 1, …, k에 해당하는 직교다차항(orthogonal polynomials)을 나타냅니다.

이미 복잡한 내용이 되버리기는 했지만, 이것이 모형식과 모형행렬의 관계의 전부가 아닙니다. 우선, 요인은 포함하지만 절편(intercept)은 포함하지 않는 모형을 생각해 볼 수 있습니다. 이 경우 포함된 요인의 모든 수준(level)을 표현할 수 있도록 k개의 열로 코딩 되어야합니다. 두번째로 고려할 점은, options을 사용하여 대조(contrasts)를 사용하는 방식을 변경할 경우, 모형에서 요인을 표현하는 방법이 완전히 달라지게 된다는 점입니다 .R에서는 디폴트(default)로 아래와 같이 지정되어 있습니다.

options(contrasts = c("contr.treatment", "contr.poly"))

이 부분을 따로 언급하는 이유는, R과 S에서 비순서형 요인(unordered factor)에 대해 다른 디폴트(default) 코딩을 사용하고 있기 때문입니다; S의 경우는 Helmert 방식을 사용합니다.또 다른 경우는 비순서형 요소를 사용할 경우, R과 S의 기본동작이 서로 다르다는 것입니다.S의 경우는 Helmert라는 방식을 이용합니다.따라서, 만약 S-PLUS를 사용한 결과를 바탕으로 쓰여진 책이나 논문의 내용을 R로 분석한 결과물과 비교해 보고 싶다면, 다음과 같은 설정이 필요 합니다.

options(contrasts = c("contr.helmert", "contr.poly"))

R에서 디폴트(default)로 treatment 대조를 채택한 이유는, 이 방법을 처음 다루는 초보자들에게는 treatment 대조로 생성된 결과를 해석하는 것이 쉬울것이라 믿었기 때문입니다.

이번에는 함수 contrastsC를 사용하여 각각의 항을 모형에 포함시키기 위한 대조(contrast)의 사용법(scheme)을 좀 더 자세히 다뤄보도록 하겠습니다.

우리는 어떤 식으로 교차항(interaction terms)을 모형에 포함할지에 대해서도 아직 다루지 않았습니다.교차항은 교호작용을 구성하는 변수들의 해당 열을 서로 곱(product)하여 생성합니다.

교차항을 다루기 위한 세부사항들은 너무 복잡하기 때문에, 여기서 다루지는 않겠습니다. 하지만, R에서 모형을 사용하는 방법은 보통의 통계 전문가라면 예측할만한 방식을 크게 벗어나지 않습니다. 하지만 몇몇 예외가 있을 수 있는데, 교호작용(interaction)은 포함하지만 이에 대응하는 주효과(main effects)는 포함하지 않는 모형을 사용하는 것이 하나의 예가 될 수 있을 것입니다. 이 경우 일반적으로 기대하는 것과는 많이 다른 결과가 얻어질 수 있는데, 이는 아마도 이 분야 전문가들이나 관심을 가질만한 주제일 것 입니다.


11.2 Linear models

일반(ordinary) 다중(multiple,여러 개 항을 포함하는)모형을 적합하는 가장 간단한 방법은 아래와 같이 함수 lm()를 이용하는 것입니다:

> fitted.model <- lm(formula, data = data.frame)

다음의 예시를 살펴봅니다.

> fm2 <- lm(y ~ x1 + x2, data = production)

예를 들면, 아래의 코드는 종속변수 y를 설명변수 x1x2에 회귀시킨 다중회귀모형(multiple regression model)을 적합시킵니다.(따로 표시된 것은 아니지만, 상수항(intercept term)이 항상 포함된다는 점을 잊지 마시기 바랍니다.)

위 식에 사용된 것 중 중요한 (하지만 이 함수의 실행을 위해서는 반드시 필요한 것은 아닌) 모수(parameter)로는 data = production가 있습니다. 이 모수는 선형모형을 적합시키게 될 데이터를 지정하는 것으로, 여기서 지정된 데이터 프레임(data frame) production는 반드시 모형에 포함될 모든 변수들을 포함하고 있어야 합니다. 이러한 데이터 프레임의 지정은 해당 데이터 프레임,이 예제에서는 production이, 검색 경로(search path)상에 연결되었건(attached) 그렇지 않든 상관없이 동일하게 이루어져야 합니다.


11.3 Generic functions for extracting model information

lm()을 사용하면 적합된 선형모형을 하나의 객체로 얻게됩니다; 이 객체는 클래스(class)가 "lm"인 여러 개의 결과물로 구성된 하나의 리스트 입니다. 이렇게 lm() 함수를 사용해 적합된 모형에 관련된 정보는 일반함수(generic functions)를 사용하여 생성된 결과물을 출력하거나, 일부 정보만을 따로 추출하거나, 또는 플롯을 그리는 등 다양하게 활용할 수 있습니다.이렇게 모형 정보를 다룰 수 있는 일반함수에는 다음과 같은 종류가 있습니다.

add1    deviance   formula      predict  step
alias   drop1      kappa        print    summary
anova   effects    labels       proj     vcov
coef    family     plot         residuals

이 중에서 가장 빈번하게 사용되는 일반함수들에 대해서 아래와 같이 정리해 보았습니다.

anova(object_1, object_2)

이 함수는 두개의 적합된 모형을 비교하는 것으로, 분산분석표를 제공 합니다. (여기서 사용된 두 개의 모형은 임의로 선택된다기 보다는 하나의 새 모형(outer model)과 이 모형의 일부를 포함하는 다른 모형(submodel)이어야 합니다.)

coef(object)

적합된 선형계수를 (행렬의 형태로) 추출해줍니다.여기에서 coef()coefficients()라는 원래 함수의 약어 표현입니다.

Long form: coefficients(object).

deviance(object)

잔차(residual)를 제곱하여 이를 모두 더한 값을 출력하며, 경우에 따라서는 weighted 된 잔차를 사용할 수도 있습니다.

formula(object)

object를 적합하는데 사용한 모형식(model formula)을 보여줍니다.

plot(object)

object의 잔차(residuals)와 적합된 값(fitted values)을 보여주는 4가지 플롯과 함께 몇가지 모형진단(diagnostics)통계량을 제공합니다.

predict(object, newdata=data.frame)

적합된 모형을 사용하여 예측값(predicted values)를 구해줍니다. 이때 예측에 사용될 데이터 프레임은 반드시 원래의 모형적합에 사용된 데이터와 같은 변수명을 가져야 합니다. 이 함수를 사용한 결과로 data.frame으로 입력된 변수값을 이용하여 계산된 예측값이 벡터 또는 행렬로 출력됩니다.

print(object)

객체를 간결한 형태로 출력합니다. 많은 경우, 별도의 입력 없이도 결과가 출력됩니다.

residuals(object)

적합된 모형에 대한 잔차 또는 weighted 잔차를 (행렬의 형태로) 추출합니다. (원래의 residuals() 함수를 약어인 resid(object)로 사용하실 수도 있습니다.)

Short form: resid(object).

step(object)

스텝와이즈 (stepwise) 검색으로 최적모형을 찾아줍니다. 변수의 중요도(hierarchies)에 따라 한번 하나씩 항을 추가하거나 제거함으로서 적당한 모형을 선택하는 방법입니다. 스텝와이즈 검색을 사용할 경우, 가장 작은 AIC(Akaike’s Information Criterion)값을 갖는 모형을 선택하게 됩니다.

summary(object)

회귀분석의 결과를 간결한 형태로 요약하여 보여줍니다.

vcov(object)

적합된 회귀계수들에 대한 분산-공분산 (variance-covariance) 행렬을 출력합니다.


11.4 Analysis of variance and model comparison

The model fitting function aov(formula, data=data.frame) 분산분석(analysis of variance)을 수행하기 위해 aov(formula, data=data.frame) 함수를 사용할 수 있습니다. 이 함수는 lm() 함수와 대체로 비슷한 연산을 수행한다고 볼 수 있으며, 따라서 위의 Generic functions for extracting model information편에서 열거한 일반함수(generic functions)들을 거의 그대로 사용할 수 있습니다.

하지만, aov()함수는 오차의 다중계층(multiple error strata)구조를 가정한 모형을 다룰 수 있어, 분할법 실험(split plot experiment)이나 블럭간(inter-block)정보를 사용한 균형 불완비블럭설계(balanced incomplete block design)와 같은 모형을 분석하기 위해 사용할 수 있다는 큰 장점을 가지고 있습니다. 모형식은 다음과 같이 사용할 수 있습니다.

response ~ mean.formula + Error(strata.formula)

위 식은 strata.formula에 정의된 대로 오차의 계층(error strata)구조를 가정한 다계층실험 (multi-stratum experiement)을 표현한 것입니다.가장 간단한 경우로, 요인의 수준(levels)간(between) 차이와 수준내(within) 차이만 고려하는 2계층-실험(two strata experiment)이 있고, 이 경우 strata.formula는 단순히 하나의 요인이 됩니다.

구체적인 예를 들면, 모형을 구성하는 모든 변수와 요인을 사용하여 아래와 같은 모형식(model formula)을 작성할 수 있습니다:

> fm <- aov(yield ~ v + n*p*k + Error(farms/blocks), data=farm.data)

이 식은 보통 v + n*p*k로 표현되는 평균 모형(mean model)으로 실험을 기술할 때 사용되며, 이 경우 “between farms”, “within farms”, 그리고 “within blocks”라는 세 개의 오차계층(error strata)을 포함합니다.


11.4.1 ANOVA tables

분산분석(the analysis of variance,ANOVA)(또는 분산분석표)은 사실 여러 개의 모형을 적합한 결과를 나타내고 있다는 점을 이해할 필요가 있습니다. 보통 잔차합 (sums of squares,SS)은 주어진 시퀀스의 해당 위치(that place)에 있는해당 변수(that term)를 모형에 하나씩 포함시킬때 마다 점점 감소합니다. 즉, 오직 직교실험(orthogonal experiment)의 경우에만 항을 추가해나가는 순서가 중요하지 않습니다.

다계층실험(multistratum experiments)의 경우, 우선 종속(response)변수를 오차계층(error strata)에 시퀀스 순서대로 정사영(project)시켜 나가면서, 각 정사영마다 평균모형( mean model)을 적합하는 과정을 통해 분산분석을 수행하게 됩니다. 여기에 대한 자세한 설명은 Chambers & Hastie (1992)의 책을 참고하시길 바랍니다.

이렇게 디폴트(default) ANOVA 테이블로 각 모형을 따로 적합한 결과들을 비교하는 것 보다는 좀 더 쉽게, 두개 이상의 모형들을 한번에 비교하고 싶다면, anova() 함수를 사용하면 됩니다.

> anova(fitted.model.1, fitted.model.2, …)

anova() 함수를 사용하면, 입력한 순서대로 적합된 모형 간의 차이를 보여주는 테이블을 생성합니다.이때, 비교하게 될 모형들은,물론 일종의 계층적 순서(hierarchical sequence)를 가져야만 합니다.anova() 함수를 사용하는 것이 디폴트(default) 함수를 사용했을 때와 다른 정보를 더 제공하는 것은 아니지만, 좀 더 이해하기 쉽고 손쉽게 모형을 비교하기 위해 사용한다고 보시면 됩니다.


11.5 Updating fitted models

update() 함수는 이미 적합된 모형에 몇 개의 항만을 추가하거나 혹은 제거해서 새로운 모형으로서 적합시키고자 할 때 매우 유용하게 사용할 수 있으며, 다음과 같이 사용합니다.

> new.model <- update(old.model, new.formula)

위 식의 new.formula 부분에서 마침표(period) ‘.’ 하나가 사용될 경우, 이것은 "이전 모형으로부터 온 부분들"이라는 의미로 사용된 것 입니다. 좀 더 확실한 이해를 위해 아래의 예제를 살펴봅시다.

> fm05 <- lm(y ~ x1 + x2 + x3 + x4 + x5, data = production)
> fm6  <- update(fm05, . ~ . + x6)
> smf6 <- update(fm6, sqrt(.) ~ .)

제일 먼저 데이터 프레임 production으로부터 온 5개의 변수를 포함하는 중회귀(multiple regression) 모형(fm05)을 적합하고, 이를 바탕으로 6번째 변수를 추가하여 모형을 다시 적합한 후(fm6), 다시 이 모형에서 제곱근(square root) 변환시킨 종속변수를 사용하여 모형을 적합한 것입니다 (smf6).

특히, 제일 처음으로 사용한 모형 적합 함수에서 data= 인자(argument)가 지정된 경우에는, 이 정보가 모형 적합에 사용되는 과정을 통헤 update() 함수와 그 함수족(allies)을 사용할 경우 그대로 전달되어 사용된다는 점을 기억하시기 바랍니다.

또, ‘.’는 다른 상황(contexts)에서 사용될 때는 위에서 설명한 것과 약간 다른 의미로 사용된다는 점도 주의해야 합니다. 아래의 예에서는,

> fmfull <- lm(y ~ . , data = production)

종속(response)변수 y와 함께 데이터 프레임 production에 포함된 모든 변수들을 회귀변수로 사용하는 모형을 적합하겠다는 의미입니다.

순서대로 항을 늘려가며 모형을 비교하기 위해서는 add1(), drop1() 그리고 step()와 같은 함수들을 사용할 수 있습니다. 이 함수들은 이름 그대로의 의미로 사용할 수 있으며,더 자세한 사항은 각 함수의 도움말을 살펴보시길 바랍니다.


11.6 Generalized linear models

일반화 선형 모델(generalized linear model)이란 정규분포가 아닌 분포를 갖는 종속변수(non-normal response)와 변수변환(transformation)을 통한 선형성(linearity)의 만족이라는 두 과제를 깔끔하게 해결하기 위해 선형모형(linear model)을 좀 더 발전시킨 것이라고 생각하시면 됩니다.일반화 선형 모형은 다음과 같은 가정(assumptions)들을 사용하여 정의할 수도 있습니다:

위의 가정들은 통계실무에서 사용하는 꽤 광범위한 클래스의 모형들을 포함할 수 있는 최소한의 가정이지만, 추정(estimation)과 추론(inference)을 하기 위한 하나의 통일된 방법론(methodology)이나 그 비슷한 것을 개발할 수 있을 만큼 충분히 구체적이기도 합니다. 일반화 선형 모형의 최신 레퍼런스나 좀 더 자세한 정보에 관심이 있는 분들께는 McCullagh & Nelder (1989)와 Dobson (1990)을 찾아보실 것을 권하고 싶습니다.


11.6.1 Families

R에서는 일반화 선형모형에서 종속변수의 분포가 가우시안(gaussian = 정규분포), 이항 (binomial), 포아송 (poisson), 역가우시안 (inverse gaussian), 그리고 감마 (gamma)인 경우를 모두 다룰 수 있으며, 또 종속변수의 분포가 분포 함수에 의해 정확히 묘사될 수 없는 경우에 사용하는 쿼시-라이클리후드 (quasi-likelihood) 모형 역시 지원합니다.특히 쿼시-라이클리후드 모형의 경우, 분산함수(variance function)를 반드시 평균(mean)의 함수식 형태로 나타낼 수 있어야 하지만, 이 외의 다른 경우에는 종속변수의 분포가 분산함수(variance function)의 형태를 내포합니다.

종속변수의 각 분포들은 아래와 같이 다양한 연결함수(link functions)를 사용하여 이 분포의 평균과 linear predictor를 연결합니다. 사용가능한 분포와 연결함수는 다음과 같습니다:

Family nameLink functions
binomiallogit, probit, log, cloglog
gaussianidentity, log, inverse
Gammaidentity, inverse, log
inverse.gaussian1/mu^2, identity, inverse, log
poissonidentity, log, sqrt
quasilogit, probit, cloglog, identity, inverse, log, 1/mu^2, sqrt

종속변수의 분포와 연결함수, 그리고 모형을 실행하기 필요한 다른 모든 정보들의 조합을 일반화 선형모형에서의 분포족(family)이라고 합니다.


11.6.2 The glm() function

일반화 선형모형에서도 종속변수의 분포가 오직 단순 선형함수의 형태로만 설명변수들과 연관되기 때문에, 선형모형 적합에 사용된 방법이 일반화 모형의 선형 부분에도 그대로 적용될 수 있습니다. 다만, 분포족(family)을 지정해야한다는 차이가 있습니다.

일반화 선형모형을 적합하는데 사용하는 R 함수는 glm()이며, 아래와 같이 사용합니다.

> fitted.model <- glm(formula, family=family.generator, data=data.frame)

(lm()함수와 비교했을 때) 유일하게 하나 첨가된 기능은 함수족.생성자(family.generator)이며, 어떤 함수족을 모형에 사용할 것인지를 지정해주는 도구 같은 것입니다. 이 함수는 해당 모형과 그 추정(estimation)을 정의하고 실행하기위해 필요한 함수들과 표현식들의 리스트를 생성해 줍니다. 언뜻 매우 복잡할 것처럼 보일 수도 있지만, 사실 사용하기 매우 간단한 함수 입니다.

함수족 생성자(family generator)에 사용될 수 있는 분포들의 표준 표기명은 Families 섹션에 있는 표에서 "함수족 이름 (Family Name)" 부분에서 찾으실 수 있습니다. 또 연결함수를 따로 선택하고 싶은 경우, 모수(paramter)를 지정할 때 처럼, 분포족(family)이름 옆 괄호(parentheses) 안에 연결함수의 이름을 입력하시면 됩니다. 또 쿼시(quasi)족의 경우, 분산함수(variance function)를 이와 비슷한 방식으로 입력할 수 있습니다.

아래의 예들을 살펴보시면 사용법이 좀 더 분명하게 이해될 것입니다.

The gaussian family

아래와 같이 glm() 함수를 사용하면 lm()을 사용할 때와 같은 결과를 얻긴하지만 훨씬 비효율적입니다.

> fm <- glm(y ~ x1 + x2, family = gaussian, data = sales)

achieves the same result as

> fm <- lm(y ~ x1+x2, data=sales)

가우시안족(gaussian family)은 연결함수의 선택이 그다지 필요하지 않기 때문에, 굳이 모수(parameter)를 지정할 필요가 없다는 점을 생각해보시기 바랍니다. 만약 가우시안족(gaussian family)에 표준이 아닌 (nonstandard) 연결함수를 사용하고 싶다면, 뒤에서 다루게 될, 쿼시족(quasi family)을 사용하는 것이 보통입니다.

The binomial family

Silvey (1970)에서 사용된 간단한 예제를 살펴봅시다.

에게해의 한 섬인 Kalythos에는 남성들이 선천성 안질환을 앓고 있는데, 이 안질환은 주로 나이가 들어감에 따라 더욱 진행됩니다. 아래의 데이터는 이 섬에 거주하는 다양한 연령대의 남성들의 실명여부를 검사한 결과를 기록한 것입니다:

Age:2035455570
No. tested:5050505050
No. blind: 617263744

이 데이터에 로지스틱(logistic)과 프로빗(probit) 두가지 모형을 모두 적합시키고, 각 모형으로부터 남성거주자의 실명확률이 50%가 되는 나이인 LD50를 추정하고자 합니다.

만약 y가 연령 x 때의 테스트에서 확인된 실명한 사람들의 수이고, n은 테스트를 받은 사람의 수라면, 두 모형은 아래와 같이 표현됩니다. y ~ B(n, F(beta_0 + beta_1 x)) 프로빗 모형의 경우, F(z) = Phi(z) 표준 정규 분포(standard normal distribution function)를, 로짓 모형의 경우, F(z) = e^z/(1+e^z) 입니다.두 경우 모두 LD50는 LD50 = - beta_0/beta_1 으로 계산할 수 있으며, 이 값은 분포함수 F(z)의 값이 0일 때의 z에 해당합니다

위 문제를 풀기위한 첫번째 단계로 우선 모형에서 다루게 될 데이터를 데이터 프레임의 형식으로 준비합니다.

> kalythos <- data.frame(x = c(20,35,45,55,70), n = rep(50,5),
                         y = c(6,17,26,37,44))

glm() 함수를 이용하여 이항모형(binomial model)을 적합할 경우에는, 아래의 세가지 종속변수(response) 종류 중 한 가지를 선택하실 수 있습니다:

이 예제에서는 이 중 두번째 방법을 사용할 것입니다, 따라서 아래와 같이 행렬 하나를 준비된 데이터 프레임 안에 추가하겠습니다.

> kalythos$Ymat <- cbind(kalythos$y, kalythos$n - kalythos$y)

모형의 적합은 아래와 같습니다.

> fmp <- glm(Ymat ~ x, family = binomial(link=probit), data = kalythos)
> fml <- glm(Ymat ~ x, family = binomial, data = kalythos)

logit 연결함수가 디폴트이므로, 두번째 식에서는 해당 모수(parameter)의 입력은 생략될 수 있습니다. 각 모형의 적합된 결과를 확인하기 위해,

> summary(fmp)
> summary(fml)

두 모형 모두 적합결과가 아주 좋습니다. LD50을 추정하기 위해, 다음과 같은 간단한 함수를 작성할 수 있습니다:

> ld50 <- function(b) -b[1]/b[2]
> ldp <- ld50(coef(fmp)); ldl <- ld50(coef(fml)); c(ldp, ldl)

이 데이터로부터 얻어진 실제 추정치는 각각 43.663세 와 43.601세 입니다.

Poisson models

포아송족 (Poisson family)의 경우, 디폴트로 log가 연결함수로 지정되어 있으며, 보통 실무에서 포아송족(Poisson family)을 주로 사용하게 되는 경우는 빈도데이터(frequency data)를 대체형(surrogate) (포아송) 로그선형모형(Poisson log-linear model)에 적합할 때 입니다. 로그선형모형을 대체형(surrogate)이라고 한 이유는, 빈도데이터의 경우, 실제 분포는 대체로 (포아송이 아니라) 다항분포(multinomial distribution)이기 때문입니다. 이 모형의 사용은 매우 중요하지만 너무 방대한 주제라 여기서는 다루지 않겠습니다. 사실 빈도데이터에 포아송 분포를 가정하는 모형은 비정규형(non-gaussian) 일반화 모형 전체에서 가장 대표적인 방법이라고 할 수 있겠습니다.

물론 때때로 데이터가 정말 포아송 분포에서 얻어지는 경우도 있겠지만, 이 경우 과거에는, (실무에서는 아직도) 데이터를 로그나 제곱근으로 변환하여 가우시안(gaussian) 데이터로 바꾼 다음 분석을 수행했습니다. 하지만 이제는 아래와 같이 포이송 일반화 선형모형을 적합하는 것이 가능합니다.

> fmod <- glm(y ~ A + B + x, family = poisson(link=sqrt),
              data = worm.counts)

Quasi-likelihood models

일반화 선형모형의 모든 함수족(families)에서, 종속변수의 분산은 평균에 대한 함수이며, 스케일 모수(parameter)는 계수(multiplier)입니다. 분산이 평균과 어떤 식으로 연관되는지 나타내는 식은 종속변수분포의 중요한 특성이라 볼 수 있습니다; 예를 들면, 포아송 분포의 경우 Var(y) = mu.

쿼시-라이클리후드(Quasi-likelihood)를 이용한 추정(estimation)과 추론(inference)을 위해, 정확한 종속변수의 분포를 지정할 필요는 없지만, 연결함수(link function)와 평균(mean)의 함수 형태로 분산함수(variance function)는 지정되어야 합니다. 쿼시-라이클리후드(Quasi-likelihood)를 이용한 추정에는 가우시안 분포의 경우와 완전히 동일한 방법을 사용하므로, 표준혀이 아닌 (non-standard) 연결함수 또는 분산함수(variance funtion)를 가정하는 가우시안 모형을 적합하는 데도 사용할 수 있습니다.

예를들어, 아래와 같이 비선형회귀모형을 적합할 경우 y = theta_1 z_1 / (z_2 - theta_2) + e 이 모형은 아래와 같은 방법으로 사용할 수도 있습니다. y = 1 / (beta_1 x_1 + beta_2 x_2) + e where x_1 = z_2/z_1, x_2 = -1/z_1, beta_1 = 1/theta_1, and beta_2 = theta_2/theta_1. 적당한 데이터 프레임이 존재한다고 가정하면, 위의 비선형회귀모형은 다음과 같이 적합할 수도 있습니다.

> nlfit <- glm(y ~ x1 + x2 - 1,
               family = quasi(link=inverse, variance=constant),
               data = biochem)

더 자세한 설명이 필요하면 해당 매뉴얼과 도움말을 이용하시길 바랍니다.


11.7 Nonlinear least squares and maximum likelihood models

특정한 형식을 갖춘 비선형모형은 일반화 선형모형(glm())을 사용하여 적합할 수 있습니다. 하지만 대부분의 경우, 비선형모형은 비선형 최적화(nonlinear optimization) 방법 중 하나를 사용하여 비선형 곡선(curve)에 적합시키는 방식으로 풀어야만 합니다. R은 이런 비선형 최적화 문제를 풀어주는 optim(), nlm() 그리고 (R 2.2.0 부터는) nlminb() 함수를 제공합니다. 특히, nlminb() 함수의 경우, S-PLUS에서 사용되는 ms()nlminb() 함수와 같은 (혹은 좀 더 다양한) 기능을 제공합니다. 이러한 함수를 사용할 경우, 주어진 적합결여지표(index of lack-of-fit)를 최소화시키는 모수의 값을 찾는것이 우리의 관심사이며, 위의 함수들은 모수에 여러 값을 반복적으로 대입하여 최적값을 찾습니다. 그러나, 이러한 프로시져를 사용할 경우, 선형회귀에서 모수를 추정할 때와는 달리, 만족스러울만한 추정치로 수렴하게 될거라는 보장은 없습니다. 모수 추정을 위해 초기값을 사용해야하는 모든 계산 방법에서는 이 초기값을 얼마나 잘 선택하는지에 따라 수렴결과가 크게 달라지기 때문입니다.


11.7.1 Least squares

비선형모형을 적합하는 한가지 방법은 오차 혹은 잔차들의 제곱합(the sum of the squared errors or residuals)을 최소화시키는 것입니다. 이러한 최소제곱법은 관측된 오차들이 정규분포를 따른다고 보여질 경우에 권장됩니다.

여기서 Bates & Watts (1988), page 51에 수록된 예제를 하나 살펴보도록 하겠습니다. 주어진 데이터는 아래와 같습니다.

> x <- c(0.02, 0.02, 0.06, 0.06, 0.11, 0.11, 0.22, 0.22, 0.56, 0.56,
         1.10, 1.10)
> y <- c(76, 47, 97, 107, 123, 139, 159, 152, 191, 201, 207, 200)

최소화하기 위한 적합기준을 다음과 같습니다:

> fn <- function(p) sum((y - (p[1] * x)/(p[2] + x))^2)

모형적합을 위해 모수에 대한 초기값이 필요합니다. 그럴듯한 초기값을 찾는 방법 중 하나는 데이터를 플롯시킨 후, 모수값을 추측해서, 데이터 값과 유사한 패턴을 주는 모형의 곡선을 겹쳐 그려보는 것입니다.

> plot(x, y)
> xfit <- seq(.02, 1.1, .05)
> yfit <- 200 * xfit/(0.1 + xfit)
> lines(spline(xfit, yfit))

물론 더 나은 추측값이 있을 수 있지만, 200 과 0.1 을 초기값으로 하는 것에 무리는 없어 보입니다. 이제 모형을 적합시켜 보면:

> out <- nlm(fn, p = c(200, 0.1), hessian = TRUE)

모형을 적합시키고 나면, out$minimum는 SSE를, out$estimate는 최소제곱법을 이용한 모수 추정치(estimates)를 보여줍니다. 추정치의 표준오차(standard error, SE)의 근사치는 아래 식으로 구할 수 있습니다:

> sqrt(diag(2*out$minimum/(length(y) - 2) * solve(out$hessian)))

위 식에서 숫자 2는 모형에 포함된 모수(parameter)의 개수를 의미합니다. 모수의 추정치에 대한 95% 신뢰구간은 추정치에 +/- 1.96*SE 하여 계산할 수 있습니다. 또 최소제곱법으로 구한 추정치의 핏(fit)을 데이터 플롯 위에 덧그릴수도 있습니다:

> plot(x, y)
> xfit <- seq(.02, 1.1, .05)
> yfit <- 212.68384222 * xfit/(0.06412146 + xfit)
> lines(spline(xfit, yfit))

표준 패키지인 stats에는 최소제곱법으로 비선형모형을 적합할 수 있는 많은 종류의 함수들이 포함되어 있습니다. 바로 위의 예제에서 우리는 Michaelis-Menten 모형을 적합했습니다. 이 분석은 다음과 같은 방법으로도 실행 가능합니다.

> df <- data.frame(x=x, y=y)
> fit <- nls(y ~ SSmicmen(x, Vm, K), df)
> fit
Nonlinear regression model
  model:  y ~ SSmicmen(x, Vm, K)
   data:  df
          Vm            K
212.68370711   0.06412123
 residual sum-of-squares:  1195.449
> summary(fit)

Formula: y ~ SSmicmen(x, Vm, K)

Parameters:
    Estimate Std. Error t value Pr(>|t|)
Vm 2.127e+02  6.947e+00  30.615 3.24e-11
K  6.412e-02  8.281e-03   7.743 1.57e-05

Residual standard error: 10.93 on 10 degrees of freedom

Correlation of Parameter Estimates:
      Vm
K 0.7651

11.7.2 Maximum likelihood

최우추정(Maximum likelihood)법 역시 비선형모형을 적합하는데 쓰일 수 있으며, 오차항이 정규분포를 따르지 않을 경우에도 사용할 수 있습니다. 이 방법은 로그-우도(log-likelihood) 함수를 최대화시켜주는 모수의 값을 추정치로 찾아주며, 이는 음의 로그-우도(negative log-likelihood)를 최소화시키는 모수의 값을 찾는것과 동일합니다. 이제 Dobson(1990), pp.108–111 에 나오는 예제를 살펴보도록 하겠습니다. 이 예제는 dose-response 데이터에 로지스틱 모형을 적합하는 것이며 glm()함수를 사용할 수 있습니다. 우선 주어진 데이터는 아래와 같습니다:

> x <- c(1.6907, 1.7242, 1.7552, 1.7842, 1.8113,
         1.8369, 1.8610, 1.8839)
> y <- c( 6, 13, 18, 28, 52, 53, 61, 60)
> n <- c(59, 60, 62, 56, 63, 59, 62, 60)

다음과 같이 음의 로그-우도 함수를 최소화 합니다:

> fn <- function(p)
   sum( - (y*(p[1]+p[2]*x) - n*log(1+exp(p[1]+p[2]*x))
           + log(choose(n, y)) ))

이 작업을 수행하기위해 적당한 초기값(starting values)을 선택합니다:

> out <- nlm(fn, p = c(-50,20), hessian = TRUE)

모형을 적합시키고나면, out$minimum사용해서 음의 로그-우도(negative log-likelihood) 함수값을, out$estimate를 사용해서 모수의 최대우도추정치(maximum likelihood estimates/MLE)를 확인할 수 있습니다.추정치의 표준오차(standard error, SE)의 근사치는 아래와 같이 구할 수 있습니다:

> sqrt(diag(solve(out$hessian)))

마찬가지로, 95% 신뢰구간은 모수의 추정치에 +/-1.96*SE 하여 계산하면 됩니다.


11.8 Some non-standard models

이번 장은 특수한 회귀모형 및 데이터 분석방법을 다루기 위해 R에서 이용가능한 기능들에 간단히 소개하면서 마무리하도록 하겠습니다.


12 Graphical procedures

R 환경(environment)에서 가장 중요고도 유용하게 활용되는 부분이 바로 그래픽 기능일 것입니다. R의 그래픽 기능을 사용해서, 다양한 통계 관련 그래프들을 생성할 수 있으며, 또 완전히 새로운 종류의 그래프를 만들어 내는 것도 가능합니다.

그래픽 기능들은 대화형(interactive)이나 일괄식(batch)으로 사용하는 것 모두 가능하지만,대부분의 경우에는 대화형으로 작업하는 것이 좀 더 쉽고 효과적입니다. 대화형 사용이 좀 더 쉬운 이유는, R이 시작될 때 대화형 그래픽을 출력하는 특별한 그래픽 윈도우(graphics window)를 여는 device driver(장치 드라이버)가 자동으로 초기화되기 때문입니다. 물론 이러한 과정은 자동적으로 실행되지만, UNIX에서는 X11(), 윈도우즈에서는 windows(), 그리고 Mac OS X에서는 quartz() 함수를 사용해서 그래픽 장치(graphic device)를 시작할 수 있다는 것을 알아두시면 유용할 것 입니다.

일단 장치 드라이버가 실행되면, R의 플롯팅(plotting) 명령어들은 다양한 종류의 그래픽 처리 및 새로운 종류의 그래픽 생성을 위해 사용할 수 있습니다.

플롯팅 명령어들은 다음과 같이 크게 세 그룹으로 나눌 수 있습니다:

또한, R은 사용자가 원하는대로 플롯을 수정 및 변경하는 데 사용할 수 있도록 여러 종류의 그래픽 파라미터 (graphical parameters)들을 제공합니다.

이 매뉴얼에서는 일단 ‘기본(base)’ 그래픽이라고 알려진 것들에 대해서만 다루겠습니다. 이러한 기본 그래픽과는 별도로 grid 패키지를 통해 사용할 수 있는 별도의 그래픽 서브-시스템이 존재하는데, 좀 더 강력한 그래픽 기능들을 제공하지만, 사용하기가 쉽지는 않습니다. 또, grid를 기반해서 제작된 lattice라는 권장패키지도 있는데, 이는 S에서 Trellis(트렐리스)라는 시스템이 제공하는 다중패널 플롯(multi-panel plots)과 거의 비슷한 기능들을 사용할 수 있도록 지원합니다.


12.1 High-level plotting commands

하이-레벨 플롯팅 함수들은 함수에 몇 개의 인자만 입력해도 하나의 완전한(complete) 플롯이 생성될 수 있도록 디자인 되었습니다. 따라서, 별도의 설정없이 자동적으로 적절한 위치에 축, 레이블, 그리고 제목들이 놓이게 되며 (물론 설정을 통해 바꾸는 것도 가능합니다). 하이레벨 플롯팅 명령어들은 언제나 새 플롯을 그리기 시작할 때, 필요하다면, 현재 출력 중인 플롯을 지워 버립니다.


12.1.1 The plot() function

R에서 가장 빈번하게 사용되는 플롯팅 함수는 plot() 입니다. 이는 일반함수(generic function) 중 하나 입니다: 생성되는 플롯의 종류는 (플롯의) 타입(type) 또는 함수의 첫번째 인자의 클래스(class)에 의해서 결정됩니다.

plot(x, y)
plot(xy)

만약, xy 두 개 모두 벡터이면, plot(x, y)xy의 관계를 살펴볼 수 있는 산점도(scatter plot)를 생성합니다. 하나의 인자만을 입력 받지만, 두 번째 표현 역시 같은 산점도를 출력합니다. 하지만 이 경우, 인자는 xy 두개의 컴포넌트로 구성된 리스트이거나, 또는 2 열의 행렬 형식이어야 합니다.

plot(x)

만약 x가 시계열(time-series)이면, 이 함수는 시계열 플롯(time-series plot)을 생성합니다. 또, 만약 x가 수치형 벡터인 경우에는, x의 인덱스를 xx의 값을 y로 하는 플롯을 생성합니다. 마지막으로, x가 복소수(complex) 벡터이면, 이 함수는 실수부분을 x로 허수부분을 y로 하는 플롯을 생성합니다.

plot(f)
plot(f, y)

여기서 f는 요인을, y는 수치형 벡터를 의미합니다. 첫번째 표현식은 벡터 f에 대한 막대 그래프 (bar plot)를 생성하고, 두번째 표현식은 f의 각 수준 별로 y의 박스플롯(boxplot)을 생성합니다.

plot(df)
plot(~ expr)
plot(y ~ expr)

여기에서 df는 데이터 프레임, y는 임의의 객체, expr는, a+b+c와 같이, +로 구분된 여러 개체 이름의 리스트를 의미합니다. 첫번째 표현식은 데이터 프레임에 포함된 모든 변수들을 대상으로 각 변수의 분포를 보여주고, 두번째 표현식은 expr내에 사용된 변수들만을 대상으로 분포를 보여줍니다. 마지막 세번째 표현식은 expr에 사용된 모든 변수 각각에 대한 y의 분포를 보여 줍니다.


12.1.2 Displaying multivariate data

R은 다변량 데이터를 시각화하기 위한 두 가지 매우 유용한 함수들을 제공합니다. 만약, X가 수치형 행렬 혹은 수치형 데이터 프레임이면, 아래의 명령문은

> pairs(X)

X의 열들로 구성된 변수들로 그린 페어와이즈 산점도(pairwise scatterplot) 행렬을 그립니다.이것은 X의 각각의 열()이 다른 모든 열들()에 대하여 플롯되어,총 n(n-1)개의 플롯이 생성되고, 행과 열이 모두 같은 플롯 스케일(scales)을 갖는 하나의 행렬처럼 나열됩니다.

세 개 혹은 네 개의 변수만을 사용할 경우에는 coplot을 사용하는 것이 보다 효과적일 수 있습니다. ab는 수치형 벡터이고, c는 수치형 벡터 혹은 요인(factor)인 경우 (세 벡터는 모두 길이가 같아야 합니다.),다음의 명령문을 사용하면,

> coplot(a ~ b | c)

c가 요인인 경우에는, 이 함수는 주어진 c의 각 수준에서 a(y)에 대한 b(x)의 산점도를 그립니다. 또, c가 수치형 벡터인 경우에는, c를 몇 개의 조건부 구간 (conditioning intervals)로 나누어 각 구간에서 그 구간에 해당하는 c값을 갖는 데이터를 대상으로, a(y)에 대한 b(x)의 산점도를 그립니다. 이 조건부 구간의 개수와 위치는 coplot() 함수의 given.values= 인자를 설정하여 조정할 수 있습니다. 함수 co.intervals()와 병행하여 사용하면 구간선택시 매우 유용합니다— 이 경우, co.intervals() 함수는 구간을 선택하는데 도움을 줄 수 있습니다. 또한, 주어진 두 개의 변수에 대해 이 플롯을 그리고 싶다면, 아래와 같이 명령문을 사용하시면 됩니다.

> coplot(a ~ b | c + d)

이 명령문은 cd의 결합 조건부 구간(joint conditioning interval)을 생성하여, 각 구간별로 a(y)에 대한 b(x)의 산점도를 그립니다.

coplot()pairs() 함수는 모두 panel=이라는 인자를 가지는데,이 인자를 설정함으로써 각각의 패널에 어떤 종류의 플롯을 그릴것인지 선택할 수 있습니다. 디폴트(default)로는 산점도를 생성하는데 사용되는 points()라는 설정되어 있지만, xy 두 벡터를 사용하는 다른 종류의 로우-레벨 그래픽 함수를 panel=에 입력하여 원하는 형태의 플롯으로 바꿀 수 있습니다.coplot()에 사용될 수 있는 유용한 패널함수 중 하나로 panel.smooth()가 있습니다.


12.1.3 Display graphics

다른 하이-레벨 그래픽 함수들은 다른 종류의 플롯을 생성하는 데 사용됩니다.사용가능한 함수 중 몇 가지는 다음과 같습니다.

qqnorm(x)
qqline(x)
qqplot(x, y)

다음은 분포 비교(Distribution-comparison)를 위한 플롯을 생성하는 함수들에 대해 다루겠습니다.첫번째 표현식은 수치형 벡터 x(y)를 정규 순서통계량의 기대값(expected Normal order score(x)에 대해 플롯한 정규스코어플롯(Normal scores plot)을 생성합니다. (즉, 이 플롯의 x 값으로는 정규 분포를 따르는 순서통계량이 (플롯 생성시 Theoretical Quantiles로 레이블 됨), y 값으로는 실제 데이터의 분포를 따르는 순서통계량이 (플롯 생성시 Sample Quantiles로 레이블 됨)이 사용됩니다. 두번째 표현식은 첫번째 표현식을 통해 얻은 플롯에 데이터와 정규분포의 4분위수(quartiles)들를 지나는 직선을 더해줍니다. 세번째 표현식은 x의 분위수(퀀타일, quantiles)에 대해 y의 분위수(quantiles)를 플롯하여, 두 분포를 비교할 수 있도록 합니다.

hist(x)
hist(x, nclass=n)
hist(x, breaks=b, …)

수치형 벡터 x에 대한 히스토그램을 생성합니다. 플롯하기 위해 필요한 클래스의 개수는 알아서 적절하게 선택되지만, 구간의 개수를 지정하고 싶다면 nclass= 인자(argument)를 입력하시면 됩니다. 또한, 브레이크 포인트/각 클래스의 끝점(breakpoint)의 개수를 지정하고 싶으면 breaks= 인자(argument)를 정확히 원하는 값으로 지정하시면 됩니다.만약, probability=TRUE 인자가 입력되면, 히스토그램의 막대(bars)들은 전체 도수(counts)대신 막대의 넓이(bin width)로 나누어진 상대적 빈도(relative frequencies)가 됩니다.

dotchart(x, …)

x에대한 점도표(다트 챠트, dotchart)를 그립니다. 점도표에서는 y-축은 데이터 x에 대응되는 데이터의 레이블이, x-축에는 데이터의 값이 표시됩니다.이 플롯으로 정해진 범위의 값을 갖는 데이터들을 선택적으로 보여주는 작업을 쉽게 할 수 있습니다 .

image(x, y, z, …)
contour(x, y, z, …)
persp(x, y, z, …)

3개의 변수로 플롯을 그리는 방법들입니다. image 플롯은 서로 다른 z 값을 나타내기 위해 여러 색을 사용하며, 여러 개 직사각형들을 포함하는 하나의 그리드(grid)를 그립니다. 또한, contour 플롯은 z의 값을 표현하기 위해 여러 개의 등고선 (contour lines)을 사용하며, persp 플롯은 3차원 표면도(surface plot)을 그립니다.


12.1.4 Arguments to high-level plotting functions

하이-레벨 그래픽 함수에 자주 사용되는 인자들에는 다음과 같은 것들이 있습니다.

add=TRUE

이 함수를 로우-레벨 그래픽 함수처럼 사용하여, 현재의 플롯 위에 새로운 플롯을 겹쳐 그리도록 합니다 (모든 함수에 적용 가능한 것은 아닙니다).

axes=FALSE

축이 생성되지 않도록 해주는 인자로, 사용자가 직접 axis() 함수로 축을 지정할 때 유용하게 사용할 수 있습니다.디폴트는 axes=TRUE이며, 따라서 하이-레벨 플롯은 축을 포함합니다.

log="x"
log="y"
log="xy"

x, y 또는 두 축 모두를 log(로그)변환(logarithmic) 합니다.인자는 많은 종류의 플롤세 사용할 수 있지만, 모든 함수에 전부 적용될 수 있는 것은 아닙니다.

type=

type= 인자는 생성될 플롯의 종류를 지정하는 것으로, 아래와 같이 사용할 수 있습니다:

type="p"

(디폴트로 지정되어 있으며,) 개별 포인트(점)들로 플롯합니다.

type="l"

선으로 플롯합니다.

type="b"

포인트와 이들을 연결한 선 두가지 모두를 플롯합니다.

type="o"

포인트들과 이들을 지나는 선을 플롯합니다.

type="h"

0에서부터 시작해서 각 포인트의 높이까지 세로로 이어진 수직선들을 플롯합니다. (하이-덴서티(high-density)플롯이라고도 하며, 히스토그램"처럼" 생겼으나, 선으로 그려진 플롯입니다.)

type="s"
type="S"

스텝(계단)함수 (step-function)를 플롯합니다. 첫번째 표현식에서는 점핑포인트에서 수직선의 윗부분이, 두번째 표현식에서는 점핑포인트에서 수직선의 아랫부분이 해당 데이터 포이트의 값(y)에 대응됩니다.

type="n"

이 인자를 선택하면 화면에 아무것도 플롯되지 않습니다. 하지만, (디폴트에 의해) 축은 여전히 그려지고, 그에 따라 입력된 데이터에 대한 좌표시스템 역시 설정되어집니다. 이러한 기능은 로우-레벨 그래픽 함수를 이용하기 전 이를 적용할 틀을 만드는 데 사용하면 좋을 것입니다.

xlab=string
ylab=string

x축과 y축에 대한 레이블을 표기합니다.이 인자들을 입력하면, 하이-레벨 플롯팅 함수에 입력했던 객체들의 이름이 축 이름으로 레이블되는 디폴트 설정을 바꿀 수 있습니다.

main=string

플롯의 윗 부분에 (플롯에 사용된 것 보다) 큰 폰트로 주제목(title)을 표시합니다.

sub=string

x-축 바로 밑에, 주제목보다는 약간 작은 폰트로 부제목을 표시합니다.


12.2 Low-level plotting commands

하이레벨(high-level)플롯팅 함수를 사용하면, 때때로 내가 원하는 것을 정확히 반영한 플롯을 그릴 수 없는 경우가 생깁니다.이럴 때, 로우-레벨(low-level) 플롯팅 함수들을 이용하면 현재 플롯에 포인트, 선 또는 텍스트 같은 부가적인 정보를 더할 수 있습니다.

유용하게 사용할 수 있는 로우-레벨 플롯팅 함수들에는 다음과 같은 것들 같습니다.

points(x, y)
lines(x, y)

현재의 플롯에 포인트나 선을 추가합니다. 위 함수들은 plot()함수에서 type= 인자를 지정하는 것과 같은 작업을 수행합니다. (이 인자의 디폴트값인 "p"points()함수와, 이 인자의 "l" 값은 lines()와 동일합니다.)

text(x, y, labels, …)

x,y에 해당하는 점의 위치에 텍스트를 추가합니다. 보통 레이블(labels)은 하나의 정수나 문자형 벡터이며, i 번째 데이터의 레이블/labels[i](x[i], y[i])의 위치에 표시됩니다. (별도의 레이블이 지정되지 않더라도) 디폴트로 1:length(x) 겂이 사용됩니다.

주의: 이 함수는 다음과 같은 순서로 사용되어야 합니다.

> plot(x, y, type="n"); text(x, y, names)

그래픽 파라미터(parameter)인 type="n"은 포인트를 보이지 않게 하지만 좌표축(axes)은 이미 설정되어 있으며, text()함수는 names에 문자형 벡터를 입력된 경우, 원래 포인트의 위치에 (입력된 벡터에 저장되어 있는) 문자값을 출력합니다.

abline(a, b)
abline(h=y)
abline(v=x)
abline(lm.obj)

기울기 b이고 절편이 a인 직선을 현재의 플롯에 첨가합니다. h=y는 높이가 y인 플롯 전체를 가로지르는 수평선(horizontal line)을 그리기 위해, 마찬가지로 v=x은 (x축에서) x 좌표값을 갖는 수직선(vertical line)을 그립니다. 또, lm.obj 는 (모형적함으로 얻어진) 길이 2인 회귀계수(coefficients)들을 성분으로 갖는 리스트이며, 이 경우에는 이 두 숫자는 순서대로 (플롯에 첨가될 선의) 절편과 기울기로 사용될 것입니다.

polygon(x, y, …)

(x, y)의 형태로 입력된 꼭짓점(vertices)들을 순서대로 연결해서 다각형(polygon)을 그립니다. (옵션으로) 그려진 다각형의 내부에 해치 라인(hatch line)을 사용해서 음영을 주거나,사용중인 그래픽 장치가 지원가능할 경우, 색으로 내부를 채우는 것도 가능합니다.

legend(x, y, legend, …)

지정된 위치에 현재 플롯의 범례(legend)를 첨가합니다. 범례(legend)에는 문자형 벡터로된 (해당 플롯의) 레이블과 함께 플롯에 사용됐던 문자, 선의 종류, 색 등을 함께 사용하는 것이 가능합니다. 이렇게 레이블 이외의 다른 요소들을 사용하기 위해서는, v 이외의 최소한 한개 이상의 인자가 입력되어야 하며, (이 인자는 v와 같은 길이를 가진) 이미 플롯에 사용된 것과 같은 값들을 가지고 있어야 합니다. 다음과 같이 말이지요:

legend( , fill=v)

(다각형의) 영역을 채울게 될 색상들

legend( , col=v)

포인트나 선에 사용될 색상들

legend( , lty=v)

선의 종류

legend( , lwd=v)

선의 굵기

legend( , pch=v)

(문자형 벡터로) 입력된 문자들을 출력

title(main, sub)

현재 플롯의 윗부분에 큰 글시로 주요(main) 제목을 첨가하고 (선택에 의해) 좀 더 작은 크기의 클씨로 부(sub)제목을 아랫 부분에 표시합니다.

axis(side, …)

현재 플롯에 첫번째 인수에 (side) 지정된 방향에 축(axis)을 첨가합니다. (이 side1부터 4까지의 숫자로 나타나며, 바닥(bottom)에서 시작해 반시계 방향으로 해당 사면을 의미합니다.) 이 함수에 다른 인수들을 지정하여 축의 위치를 플롯의 내부나 옆으로 바꾸거나, 틱마크와 레이블의 위치를 조정할 수도 있습니다. 또 사용자 정의대로 축을 생성하기위해, plot() 함수에서 axes=FALSE로 입력하고 이 함수로 새축을 생성할 수도 있을 것입니다.

로우-레벨(Low-level) 플롯팅 함수들은 대체로 새로운 플롯의 구성요소를 어디에 배치할지 위치를 (xy 좌표로) 지정해주어야 합니다. 이러한 위치는 이미 사용된 하이-레벨 그래픽 명령어에의해 생성된 사용자 좌표 (user coordinates)에 의해 표현되어야하며, 이러한 좌표 시스템은 주어진 데이터에 의해 결정되는 것입니다.

xy 인자가 필요한 경우, xy라는 이름을 가진 두 요소를 묶은 하나의 리스트를 하나의 인자로 입력하는 것 역시 가능합니다. 마찬가지로 2열의 행렬을 사용하는는 것도 가능합니다. 이렇게 입력할 위치를 지정하기 위해서, locator()(아래 참조) 등의 함수를 사용하여 대화형으로(interactively) 찾은 플롯 내의 위치정보를 사용할수도 있을 것입니다.


12.2.1 Mathematical annotation

경우에 따라, 수학적 기호(symbols)나 공식(formulae)을 플롯에 첨가하는 것이 필요할 것입니다. R에서는 이러한 표현을 위해, 개별 문자열에 text, mtext, axis, 또는 title 등의 개별 함수를 사용하기 보다는 하나의 expression을 사용합니다. 예를 들면, 다음의 코드는 이항분포함수(binomial probability function)의 공식을 표현한 것입니다:

> text(x, y, expression(paste(bgroup("(", atop(n, x), ")"), p^x, q^{n-x})))

사용가능한 모든 기능에 대한 전체 리스트를 포함해, 더 많은 정보는 다음과 같은 R 명령문을 통해 확인할 수 있습니다:

> help(plotmath)
> example(plotmath)
> demo(plotmath)

12.2.2 Hershey vector fonts

textcontour 함수를 사용할 때, 텍스트를 편집하기위해 허쉬벡터폰트(Hershey vector fonts)를 사용할 수 있습니다. 허쉬폰트를 사용하는 데는 다음과 같은 세가지 정도의 이유가 있습니다:

허쉬문자표들의 리스트를 포함한, 좀 더 많은 정보는 R에서 다음과 같은 명령문을 사용해서 확인할 수 있습니다:

> help(Hershey)
> demo(Hershey)
> help(Japanese)
> demo(Japanese)

12.3 Interacting with graphics

R에서는 마우스를 사용하여 플롯에 새로운 정보를 추가하거나 제거하는 작업을 할 수 있습니다. 이런 함수들 중 가장 간단한 것으로 locator() 함수가 있습니다:

locator(n, type)

현재 플롯에서 사용자가 마우스 왼쪽 버튼을 사용하여 위치를 선택할 때까지 기다립니다. 이러한 대기 상태는, 함수는 입력된 n개(디폴트는 512)개의 점들을 모두 선택하고, 다음 번 마우스 버튼을 누를 때까지 계속 됩니다. type 인자는 선택된 포인들을 현재 플롯상에 어떻게 나타날지 결정해주는 것으로, 하이-레벨 (high-level)그래픽 함수처럼 사용됩니다; 디폴트로는 아무것도 표시되지 않도록 지정되어 있습니다. locator()는 선택된 포인트들의 위치는 xy 두 개의 요소로 구성된 하나의 리스트로 출력합니다.

하지만 locator() 함수는 인수의 입력없이 사용되는 경우가 더 많습니다. 이 함수는 범례(legends)나 레이블(labels) 같은 그래픽 요소들을 배치할 때, 이러한 요소들이 해당 그래픽 내에서 정확하게 어디에 위치하는 것이 좋을지 결정하기 어려운 경우, 대화형(interactively)으로 위치를 찾을 수 있도록 해주므로 매우 유용합니다. 예를 들면, 이상점(outlier)과 같이 특별한 데이터 포인트에 대한 정보를 표기하기위해 다음과 같은 명령문을 사용할 수 있습니다:

> text(locator(1), "Outlier", adj=0)

(locator() 함수는 현재 디바이스가 postscript와 같이 대화형 선택(interactive pointing) 기능을 제공하지 않는 경우에는 실행되지 않습니다.)

identify(x, y, labels)

xy 정보가 입력된 포인트들을 대상으로, 이 중 특정 포인트들 (마우스의 왼쪽 버튼 클릭으로 선택) 근처에 해당 포인트에 대응하는 레이블(labels) 값을 표기하여 선택된 포인트들을 구분합니다.(labels인자가 따로 입력되지 않은 경우는, 해당 포인트의 인덱스를 출력합니다). (포인트의 선택 후) 버튼을 한 번 더 누르면 선택된 포인트들의 인덱스가 출력됩니다.

때때로 우리는 포인트 위치를 미리 지정하는 대신, 해당 플롯 상에서 포인트를 직접 선택하고 싶은 경우가 있습니다. 예를 들면, 그래픽 디스플레이 상에서 관심있는 몇 개의 관측치만 선택해서, 선택된 관측치들만 따로 처리하고 싶은 경우가 있습니다. 이 경우, 두 개의 숫치형 벡터인 xy로 표현된 (x, y) 좌표쌍이 입력된 상태에서, identify() 함수는 다음과 같이 사용할 수 있습니다:

> plot(x, y)
> identify(x, y)

identify() 함수는 그 자체로 플롯을 그리지는 않지만, 사용자들이 마우스 포인터로 자유롭게 움직이다 왼쪽 버튼 클릭으로 원하는 포인트(또는 그 포인트의 근처)를 선택할 수 있도록 해줍니다. 마우스 포인터 근처에 데이터 포인터가 위치한 경우, 해당 포인트의 근처에 인덱스가 표시될 것 입니다. (이 인덱스는, 해당 포인트의 x 또는 y 벡터에서의 위치를 의미합니다). 선택된 포인트를 표기하는 또 다른 방법으로는, identify() 함수에 labels 인자를 사용해서, (해당 케이스의 이름과 같은) 좀 더 유용한(informative) 표현을 사용할 수 있도록하거나, plot = FALSE 인자를 사용하면 아무것도 표기하지않도록 지정할 수도 있습니다. (포인트를 선택하는) 프로세스가 끝나고 나면(위 참조), identify()는 선택된 포인트들의 인덱스를 출력합니다; 이 선택된 포인트들의 인덱스를 사용하면, 원래의 xy 벡터 형태로 위치를 확인하는 것도 가능합니다.


12.4 Using graphics parameters

그래픽을 생성할 때, 특히 프리젠테이션이나 출판을 위한 목적이라면, R 제공하는 디폴트만으로는 항상 원하는 형태의 플롯을 얻을 수 없을지도 모릅니다. 하지만, 그래픽 파라미터(graphics parameters)를 이용하면 거의 모든 그래프의 구성요소를 사용자가 원하는대로 바꿀 수 있습니다. R은 선의 형태, 색, 그림의 배치, 그리고 텍스트 정의 등에 이르기까지 굉장히 다양한 작업을 수행할 수 있는 그래픽 파라미터들을 제공합니다. 또 , 모든 그래픽 파라미터는 이름(e.g. ‘col’의 경우, 사용할 색을 결정하는 파라미터입니다)과 값(value, ‘col’의 경우, 숫자로 사용할 색을 지정합니다)의 두가지 요소로 구성됩니다.

현재 사용중인(active) 디바이스마다 사용할 그래픽 파라미터(parameters)의 리스트를 따로 정의하는 것이 가능하며, 각 디바스 별로 서로 다른 디폴트 파라미터들이 초기화됩니다. 그래픽 파라미터를 사용하는 방법은 크게 두 가지로 나눌 수 있습니다: 하나는, 보다 "영구적(permanently)"인 방법으로 현재 디바이스에서 사용할게 될 모든 그래픽 함수들에 영향을 미치게 되며, 좀 더 "일시적(temporarily)"인 방법은 사용하게 될 오직 하나의 그래픽 함수에만 영향을 줍니다.


12.4.1 영구적(permanent) 변환을 원할 때: par() 함수

par()함수는 현재의 그래픽 디바이스에서 사용할 그래픽 파라미터들을 지정하고 그 값을 바꾸는데 사용합니다.

par()

아무런 인수를 입력하지 않고 사용하면, 현재 디바이스에서 사용되고 있는 모든 그래픽 파라미터의 이름과 해당 파라미터들이 가진 값(values)들이 출력됩니다.

par(c("col", "lty"))

(인수의 이름들을 포함한) 문자 벡터가 인수로 사용되면, 오직 지정된 그래픽 파라미터들에 대해서만 사용 중인 값(values)이 (리스트의 형태로) 출력됩니다.

par(col=4, lty=2)

그래픽 파라미터와 해당 파라미터의 값들을 따로 인수(하나의 인수도 가능)로 지정하면, 지정된 값이 리스트로 출력됩니다.

par()함수를 사용해서 그래픽 파라미터를 지정하면 해당 파라미터와 그 값은 “영구적”으로 바뀝니다. 즉 미래에 해당 그래픽 함수를 (현재 디바이스에서) 사용하면 새로 지정된 값이 반영되어 출력되는 것 입니다. 따라서 이 방법을 사용해서 그래픽 파라미터를 지정하는 것은 일종의 “디폴트” 값을 지정하는 것과 같다고 생각할 수 있을 겁니다. 즉, 다른 값이 다시 지정되지 않는 한, 모든 그래픽 함수가 이 지정값에 영향을 받게 되는 것입니다.

par()를 사용하면, 언제나, 심지어 par()가 다른 함수 안에서 사용된 경우라도, (현재 디바이스 내) 모든 그래픽 파라미터들의 값이 (the global values of graphics parameters) 영향을 받게 된다는 점을 주의하시기 바랍니다. 이러한 결과는, 대부분의 경우 그다지 바람직하고 할 수 없을 겁니다 - 보통 우리가 바라는 것은 몇 개의 그래픽 파라미터만을 따로 지정하고, 이 상태에서 몇 개의 플롯을 작업한 후, 다시 처음의 설정으로 돌아갈 수 있도록 현재의 R 세션 전체에는 영향을 주지 않는 것입니다. 따라서, 몇 개의 그래픽 파라미터를 바꿔서 작업하고 싶은 경우, 초기값들을 par()의 결과로 저장해두면, 변경된 파라미터로 플롯 작업을 끝낸 다음에, 이 저장된 값을 실행하면 다시 초기값으로 복원됩니다.

> oldpar <- par(col=4, lty=2)
  … plotting commands …
> par(oldpar)

설정가능한 모든 그래픽 파라미터의 값을 저장했다 다시 사용하기 위해서는, 24그래픽 파라미터를 다음과 같이 지정하면 됩니다.

> oldpar <- par(no.readonly=TRUE)
  … plotting commands …
> par(oldpar)

12.4.2 인자를 사용한 일시적 변환(Temporary changes: Arguments to graphics functions)

그래픽 파라미터들은 (거의 모든) 그래픽 함수에서 적당한 인수로 사용될 수 있습니다. 인수로 사용했을 때는 오직 해당 함수가 사용되는 동안만 새로 지정한 값이 적용된다는 점을 제외하고는, par()함수 내에서 사용했을 때와 거의 같은 효과를 갖습니다. 예를 들면:

> plot(x, y, pch="+")

위 명령문의 결과로 더하기 기호(+)를 플롯 문자(plotting character)로 사용한 산점도를 그리게 되는데, 이 경우 앞으로 그리게 될 플롯의 디폴트 플롯문자를 바꾸지는 않습니다.

안타깝게도, 항상 이런 방식이 항상 일관성있게 적용되는 것은 아니므로, 경우에 따라서는 par()를 사용해서 그래픽 파라미터들을 원하는대로 지정하고 다시 되돌리는 작업을 해야할 수도 있습니다.


12.5 그래픽 파라미터 목록

앞으로 몇 개의 섹션에서는 일반적으로 많이 사용되는 그래픽 파라미터들에 대해 자세히 설명하겠습니다. par() 함수의 R 도움말 문서에 간단히 요약되어있지만, 이 문서에서는 좀 더 자세히 설명하겠습니다.

그래픽 파라미터들은 다음의 형식으로 사용됩니다:

name=value

파라미터의 효과에 대한 설명. name은 파라미터의 이름(the name of the parameter), 즉 par() 또는 그래픽 함수에서 사용할 인수의 이름을 의미합니다. value는 파라미터를 원하는대로 지정하기위해(setting) 사용하는 일반적인 값(values) 중 하나를 의미합니다.

단, 축(axes)그래픽 파라미터가 아니라, plot 함수에만 적용가능한 몇 안되는 인자들 중의 하나라는 점을 기억하시기 바랍니다: 여기에 대해서는 xaxtyaxt를 참고하시기 바랍니다.


12.5.1 그래픽 요소들의 활용(Graphical elements)

R의 플롯은 점, 선, 텍스트 그리고 (영역이 채워진) 다각형이라는 구성 요소들로 이루어져 있습니다. 이러한 그래픽 요소(graphical elements)들이 그려지는 방식을 제어하는 그래픽 파라미터에는 다음과 같은 것들이 있습니다:

pch="+"

점을 플롯팅에 사용할 문자(character)를 지정합니다. 디폴트는 그래픽 드라이버(driver)의 종류에 따라 차이가 있긴하지만, 일반적으로는 (속이 빈) 원의 형태입니다. 선택한 포인팅 문자의 종류에 따라 자동적으로 점의 위아래의 위치가 적절하게 조정되며, 예를 들면, "."의 경우 점이 가운데로 정렬됩니다.

pch=4

pch에 0에서 25사이의 정수가 입력될 경우, 각 번호에 해당하는 기호(symbol)를 사용한 플롯을 그립니다. 각 번호에 해당하는 기호(symbol)가 무엇인지 확인하려면, 다음과 같은 명령어를 사용할 수 있습니다.

> legend(locator(1), as.character(0:25), pch = 0:25)

또, 21에서 25사이의 숫자가 선택될 경우, 0에서 20 사이에 이미 사용되었던 기호(symbol)가 다른 방식으로 색이 칠해져(coloured/속이 빈 원의 경우, 까만 원으로 그려질 수 있습니다) 그려질 수 있습니다: points 에 관한 도움말과 예제를 참조하시기 바랍니다.

또한, pch32:255의 범위에 해당하는 숫자로, 현재 폰트에서 문자(character)로 사용되는, 문자나 숫자로 점을 플롯할 수 있습니다.

lty=2

선의 종류(types)를 지정하는 옵션. 이 옵션으로 지정한 선의 종류를 모든 그래픽 디바이스가 항상 출력가능한 것은 아니며, 또 디바이스의 종류에 따라 선을 출력하는 방식이 다를 수도 있습니다. 그러나 lty=1은 항상 실선(solid line)을, lty=0은 항상 선을 보이지 않게, lty=2와 그 이상의 번호는 점선(dotted)이나 파선(dashed), 혹은 이 둘을 다양하게 조합한 선으로 출력합니다.

lwd=2

선의 굵기(width)를 지정하는 옵션. “표준(standard)” 두께의 몇 배인지를 숫자로 지정하여, 원하는대로 선의 두께를 지정합니다. lines()함수로 그린 선은 물론이고, 플롯의 축(axis)선 및 다른 선들의 굵기를 조정하는 것도 가능합니다. 모든 디바이스가 이 파라미터를 지원하는 것은 아니며, 디바이스의 종류에 따라 사용가능한 선의 굵기에 제약이 있을 수 있습니다.

col=2

점, 선, 덱스트, 그리고 색으로 채워진 영역과 이미지 모두에 색을 지정하기 위해 사용 가능합니다. 현재 사용 중인 파레트 (palette, 자세한 사용은 ?palette 부분 참조)로부터 번호를 선택하거나, 또는 색 이름을 직접 입력해서 선택하는 것도 가능 합니다.

col.axis
col.lab
col.main
col.sub

비슷한 색(color)지정 파라미터들로 위와 같은 것들이 있으며, 위에서부터 순서대로 축의 주석(axis annotation), xy의 레이블(label), 주(main)타이틀과 서브(sub)-타이틀에 각각 사용 가능합니다.

font=2

정수 값을 사용하여 텍스트(text)를 출력에 사용할 폰트(font)의 종류를 지정합니다. 장치 드라이버가 지원가능한 경우, 1은 기본형 텍스트(plain text), 2는 볼드체(굸은 글씨, bold face), 3은 이탤릭체(italic), 3는 볼드 이탤릭, 그리고 5는 (그리스 문자 등을 포함하는) 기호(symbol) 폰트로 출력합니다.

font.axis
font.lab
font.main
font.sub

폰트 역시 적용하게 될 대상에 따라, 위에서부터 순서대로 축의 주석 (axis annotation), xy의 레이블(label), 주(main)타이틀과 서브(sub)-타이틀에 각각 사용 가능합니다.

adj=-0.1

플롯의 위치를 기준으로 텍스트를 상대적으로 정렬(justification)합니다. 0은 좌측정렬(left justify), 1은 우측정렬(right justify), 그리고 0.5는 플롯의 위치를 기준으로 가운데에 수평으로(center horizontally)로 정렬하는 것을 의미합니다. 즉, 지정된 숫자는 텍스트의 비율을 의미하는 것으로, 플롯의 위치에서 왼쪽을 기준으로 얼마만큼 간격을 두는지 결정합니다. 따라서, -0.1를 지정할 경우, 플롯의 위치와 텍스트 사이에 텍스트 너비(width)의 10% 만큼의 간격을 두게 됩니다.

cex=1.5

문자 (character)의 확대 비율을 지정합니다. 이 옵션의 값은 텍스트 문자(플로팅 문자(plotting characters) 포함)의 크기를 텍스트의 디폴트(default) 크기를 기준으로 했을 때의 상대적 크기로 출력합니다.

cex.axis
cex.lab
cex.main
cex.sub

역시 대상에 따라, 위에서부터 순서대로 축의 주석 (axis annotation), xy의 레이블(label), 주(main)타이틀과 서브(sub)-타이틀에 각각 적용됩니다.


12.5.2 축과 틱 마크 (tick marks)

R의 하이-레벨에 플롯(high-level plots)에서는 많은 경우 축이 자동 포함되지만, 로-레벨(low-level) 그래픽 함수인 axis() 등을 사용하여 원하는 대로 축을 지정하는 것 역시 가능합니다. 축은 세 가지 요소에 의해 결정 됩니다: 축선 (axis line) (선의 종류는 lty 그래픽 파라미터에 의해 지정됨), 틱 마크(tick marks) (축선을 따라서 단위별로 분할하는 선을 표기),그리고 틱의 레이블 (tick labels)(틱 마크의 단위 표기)가 그 세 가지 입니다. 이러한 요소들은 다음과 같은 그래픽 파라미터들을 사용하여 조정할 수 있습니다.

lab=c(5, 7, 12)

처음의 두 숫자는 각각 xy축에의 틱의 간격을 지정합니다. 세번째 숫자는 축 레이블(axis labels)이 출력될 길이(소수점 아래 길이 포함)를 (사용 가능한) 문자길이로 지정합니다. 이 파라미터가 너무 작은 값으로 선택될 경우, 모든 틱 레이블들이 반올림되어져 같은 숫자가 되어버리는 문제가 발생할 수 있습니다.

las=1

축 레이블의 정렬될 방향(orientation)을 지정합니다. 0은 축에 평행하게(parallel to axis), 1은 수평으로(horizontal), 그리고 0는 축에 수직으로(perpendicular to the axis) 레이블을 출력합니다.

mgp=c(3, 1, 0)

축 요소들에 대해 위치를 지정합니다. 첫번째 숫자는 축 레이블(axis label)에서 축의 위치까지의 거리를, 텍스트의 줄 간격으로 표시합니다. 두번째 요소는 틱 레이블까지의 거리를, 마지막 값은 축의 위치에서부터 축선까지의 거리(보통은 0)를 지정합니다. 양수 값을 지정할 경우 플롯의 영역의 바깥쪽에 해당 요소들이 나타나며, 음수값의 경우는 안쪽에 나타납니다.

tck=0.01

틱마크(tick marks)의 길이를 플롯된 영역의 크기에 대한 비율(fraction)로 지정합니다. tck이 작게 (0.5보다 작을 경우) 지정된 경우, xy 축에 표시된 틱마크들은 모두 같은 크기로 나타나게 됩니다. 1로 지정할 경우, 그리드 선(grid lines)으로 나타내며, 음수값은 플롯 영역의 바깥에 틱마크를 표시합니다.안쪽에 틱마크를 표시하고 싶다면, tck=0.01mgp=c(1,-1.5,0)를 같이 사용하세요.

xaxs="r"
yaxs="i"

각각 xy 축의 스타일을 지정합니다. 스타일이 "i" (internal)와 "r" (디폴트 (default))인 경우, 틱마크가 항상 데이타 범위 내에서만 나타나지만, "r" 의 경우 모서리에서 약간의 공백을 남기고 출력합니다. (S의 경우, R에는 적용되지 않는 다른 스타일을 사용합니다.)


12.5.3 그림 (figure)의 여백

R에서는 하나의 플롯이 하나의 그림(figure)으로 나타나며, 이 그림은 여백(margins)으로 둘러싸인 플롯 영역(plot region) (축, 레이틀, 제목 등을 포함하는)과 (많은 경우) 축에 의해 둘러싸여 있습니다.

아래는 전형적인 예입니다.

images/fig11

이러한 그림의 레이아웃 (구성 요소의 배열)은 다음과 같은 그래픽 파라미터들에의해 결정됩니다:

mai=c(1, 0.5, 0.5, 0)

순서대로 아래, 왼쪽, 위 그리고 오른쪽 여백(margin)의 너비를 조정합니다. 단위는 인치 입니다.

mar=c(4, 2, 2, 1)

위의 mai 와 같은 기능을 하지만, 유일한 차이는 텍스트의 줄 간격을 단위로 한다는 점입니다.

marmai는, 두 가지 중 하나만 사용하더라도 다른 한쪽이 영향을 받는다는 점에서, 두 함수는 동등하다고 할 수 있겠습니다. 이 파라미터는 디폴트(default)로 지정된 값이 좀 큰 편이라 조정이 필요할 것입니다; 오른쪽 여백 (margin)을 조정할 일은 거의 없다고 할 수 있으며, 윗 여백 역시 거의 사용할 일이 없을 것입니다. 하지만, 아래와 왼쪽여백의 경우, 축이나 틱레이블을 출력할 수 있을 만큼의 여백이 필요합니다. 무엇보다, 디폴트 값은 디바이스가 어느 정도의 크기로 출력할지 전혀 고려하지 않은 채 설정되어져 있습니다: 예를 들면, postscript() 드라이버를 사용할 경우, 따로 marmai를 지정하지 않고, height=4 만 사용할 경우, 플롯 크기의 반 크기에 해당하는 여백을 포함하게 됩니다. 또 여러 그래프를 중첩해서 사용할 경우 (아래 multiple figure environment 참조) 자동적으로 여백은 줄어들지만, 이렇게 줄어든 여백으로도 여러 개의 그래프를 한 페이지에 모두 출력하기에는 충분하지 않을 수 있습니다.


12.5.4 중첩된 그림 (figure) 환경

R에서는 한 페이지에 출력 가능하도록, nm 열로된 그림의 배열(array)을 생성할 수 있습니다. 각각의 그림(figure)은 각자의 여백을 포함하며, 그림의 배열(array)은 외부여백 (outer margin)을 포함하는 것이 가능합니다.

images/fig12

그래프의 중첩과 관련된 그래픽 파라미터에는 다음과 같은 것들이 있습니다:

mfcol=c(3, 2)
mfrow=c(2, 4)

여러 그림을 배열할 크기를 지정합니다. 각 파라미터의 첫번째 값은 행의 수를, 두번째 값은 열의 수를 지정합니다. 이 두 파라미터의 유일한 차이점은 지정된 틀에 그래프를 채워나가는 순서인데, mfcol의 경우 플롯을 (그리는) 순서대로 열 별로(by column) 그래프를 채워나가고 mfrow의 경우, 행별로(by rows) 그래프를 채워나갑니다.

즉, 그림의 레이아웃(layout)은 mfrow=c(3,2)과 같은 지정에 의해 생성된 것입니다; 이 그림의 경우 6개의 플롯이 모두 그려진 다음 해당 페이지를 출력하게 됩니다.

두 파라미터 중 하나가 사용될 경우, (par("cex")와 현재 디바이스에서의 폰트 크기에 영향을 받는) 기호(symbols)와 텍스트의 기본 크기(base size)가 줄어들 수 있습니다. 2행과 2열의 레이아웃의 경우, 여기에 포함된 텍스트는 기본 크기가 처음 크기의 0.83 배가 되며, 만약 세 개나 그 이상의 행이나 열이 한 레이아웃에 포함될 경우, 텍스트는 처음 크기의 0.66배가 됩니다.

mfg=c(2, 2, 3, 2)

중첩 (그림) 환경( multiple figure environment)에서 현재 그림의 위치를 지정합니다. 처음 두 개의 숫자는 현재 그림의 행과 열의 위치를 표시하며, 나중의 두 숫자는 여러 그림이 배열되었을 때의 위치를 행과 열로 표시합니다. 이미 배열이 된 그림들 사이에 간격을 주기 위해서도 이 문장을 사용할 수 있습니다. 또한 한 페이지 상의 크기가 다른 두 그림을 조정하기 위해, 이 그래픽 파라미터의 마지막 두 숫자를 실제값과 다른 값으로 지정하는 것도 가능합니다.

fig=c(4, 9, 1, 4)/10

해당 페이지에서 현재 그림의 위치를 조정합니다. 각각의 숫자들은 그림의 왼쪽, 오른쪽, 아래 그리고 위 모서리의 위치를 나타내는 것으로, 왼쪽 아래 모서리에서부터 재었을 때의 해당 페이지의 비율을 나타냅니다. 이 모수를 지정하면 한 페이지 안의 어떤 위치에라도 그림(figures)을 출력하는 것이 가능해집니다. 만약 현재 페이지에 그림을 하나 더 추가하고 싶다면, new=TRUE 라는 옵션을 함께 사용해야 합니다. (이 점은 S와 다릅니다.)

oma=c(2, 0, 3, 0)
omi=c(0, 0, 0.8, 0)

외부여백(outer margins)의 크기를 조정합니다. marmai에서와 마찬가지로, oma는 텍스트 줄 간격으로, omi는 인치 단위로 여백의 크기를 지정하며, 입력된 네 숫자는 아래여백부터 시작해서 시계 방향으로 표기한 것 입니다.

외부여백(outer margins)은 페이지 별로 표기되는(page-wise) 타이틀 등을 제대로 출력하기 위해 지정되어야 합니다. 외부 여백에 텍스트를 출력하고 싶다면, mtext() 함수와 outer=TRUE 인자를 사용하면 됩니다. 외부 여백은 디폴트로 지정되지 않았으므로, 반드시 omaomi를 사용해서 따로 지정해야마 합니다.

좀 더 복잡하게 배열된 그래픽 중첩을 사용하고 싶다면, split.screen()layout() 같은 함수들을 사용할 수 있으며, gridlattice 등의 패키지를 사용하는 것도 가능합니다.


12.6 Device drivers

R은 거의 모든 종류의 디스플레이나 프린팅 디바이스에서 (다양한 수준의) 그래픽을 생성합니다. 하지만, 이러한 작업을 시작하기전, 반드시 R에 어떤 종류의 디바이스를 사용할 것인지를 지정해야 합니다. 이러한 디바이스 지정은 하나의 장치 드라이버 (device driver)를 작동시키는 것입니다. 이렇게 장치 드라이버를 작동시켜야하는 이유는 R에서 사용된 그래픽 명령문(예를 들어, “선을 그어라” 같은)을 사용하고자 하는 디바이스가 이해할 수 있는 형태로 전환하기 위해서입니다.

장치 드라이버는 장치 드라이버 함수를 사용해서(calling) 작동시킵니다. (R에서 사용 가능한) 모든 종류의 장치 드라이버에는 이러한 기능을 가진 함수가 하나씩 있습니다: help(Devices)라고 입력하시면 사용가능한 모든 디바이스와 해당 디바이스를 작동시키는 함수의 리스트를 확인할 수 있습니다. 예를 들면, 다음과 같은 명령문을 입력하면

> postscript()

앞으로 생성하게 될 모든 그래픽 결과물들이 PostScript 포맷으로 프린터로 보내지게 됩니다. 자주 자용되는 장치 드라이버에는 다음과 같은 것들이 있습니다:

X11()

Unix와 같은 X11 윈도우 시스템을 사용하기 위한 함수

windows()

윈도우를 사용하기 위한 함수

quartz()

Mac OS X 를 사용하기 위한 함수

postscript()

PostScript로 프린터를 사용하거나, 또는 PostScript 포맷으로 된 그래픽 파일을 생성하기 위한 함수

pdf()

PDF 파일을 생성하며, 이 파일을 다른 PDF 파일에 포함시키는 것도 가능

png()

비트맵 PNG 파일을 생성하는 함수 (언제나 실행 가능한 것은 아닙니다: help 참조)

jpeg()

비트맵 JPEG 파일을 생성하는 함수로 image 플롯을 저장하기에 최적화된 방법 (언제나 실행 가능한 것은 아닙니다: help 참조)

하나의 디바이스의 사용이 끝나면, 다음과 같은 명령어를 사용해서 해당 디바이스를 종료시키는 것을 잊지 마십시기 바랍니다.

> dev.off()

이 문장을 사용하면 현재 사용 중인 디바이스를 좀 더 확실하게 종료시킬 수 있습니다; 예를 들면, 하드카피로 출력하는 디바이스를 사용 중인 경우, 이 명령문을 사용하면 각 페이지가 종료된 다음 프린터로 보내집니다. (원래 페이지의 종료는 R에서 하나의 세션이 종료될 때 자동적으로 이루어지게 됩니다.)


12.6.1 조판 문서를 위한 포스트스크립트 다이어그램 생성하기(PostScript diagrams for typeset documents)

postscript() 장치 드라이버에 file을 인수로 지정하면, 작업힌 그래픽을 PostScript 포맷으로 지정한 파일 안에 저장할 수 있습니다. 플롯은 별도로 horizontal=FALSE 지정을 하지 않는다면, 가로정렬(landscape orientation) 되며, widthheight 인수를 사용하면 그래픽의 크기를 조정할 수 있습니다 (플롯은 지정된 페이지 크기에 맞춰 자동적으로 크기가 조절됩니다).예를 들면, 다음과 같은 명령문을 사용할 경우

> postscript("file.ps", horizontal=FALSE, height=5, pointsize=10)

PostScript 코드로 된 높이가 5인치인 그림 파일 하나가 생성되며, 이 파일은 아마도 다른 문서에 포함될 수도 있을 것입니다. 만약 명령문에 사용된 파일의 이름이 이미 존재하는 파일의 이름과 같다면, 이 문장으로 실행으로 덮어쓰기(overwritten)가 되어버립니다. 이러한 덮어쓰기는 설사 해당 파일이 현재 R 세션에서 방금 전에 생성된 것이라고 하더라도 발생하게 됩니다.

PostScript 포맷을 사용하는 가장 많이 사용되는 곳은 생성된 그림(figure)을 다른 문서에 포함시키는 작업을 할 때 입니다. 이러한 작업은 파일을 PostScript 포맷으로 고정시키면(encapsulated) 훨씬 쉬워집니다: R은 별도로 onefile=FALSE 인자가 지정되지 않으면, 계속 같은 파일로(conformant) 결과를 출력합니다. 이러한 특이한 출력방식은 S 과의 호환성(compatibility)에서 기인합니다: 다시 말해, 모든 결과물이 (EPSF 기준을 따르기 때문에) 한 페이지에 출력된다는 의미입니다. 따라서, 다른 문서에 포함될 수 있는(for inclusion use) 플롯을 그리기 위해서는 다음과 같은 문장을 사용해야 합니다.

> postscript("plot1.eps", horizontal=FALSE, onefile=FALSE,
             height=8, width=6, pointsize=10)

12.6.2 다수의 그래픽 디바이스 (graphic devices)

R의 중상급 이상의 사용자라면 종종 여러 개의 그래픽 디바이스에서 동시에 작업해야할 필요를 느낄 수도 있습니다. 물론, 실제로는 한 번에 하나의 명령문이 오직 하나의 그래픽 디바이스에서만 실행되며, 이때 사용 중인 디바이스를 현재 디바이스(current device)라고 부릅니다. 여러 개의 디바이스가 사용중인 경우(open), 디바이스들은 열린 순서대로 리스트 상 하나의 위치에 할당되며, 해당 디바이스의 종류가 이름처럼 표기됩니다.

여러 디바이스들을 동시에 열어 작동시키기위해 사용할 수 있는 주요 명령문과 그 의미는 아래와 같습니다:

X11()

[UNIX]

windows()
win.printer()
win.metafile()

[Windows]

quartz()

[OS X]

postscript()
pdf()
png()
jpeg()
tiff()
bitmap()

새로운 장치 드라이버 함수를 입력할 때마다 새 그래픽 디바이스가 작동되며, 따라서 디바이스 리스트도 사용된 함수의 숫자 만큼 하나씩 길어지게 됩니다. 이렇게 작동된 디바이스는 현재 디바이스가 되며, 앞으로 생성될 그래픽 결과물은 이 현재 디바이스가 출력합니다.

dev.list()

현재 사용중인 모든 디바이스들의 개수와 이름을 보여주는 명령문. 이 리스트 상의 첫번째 위치(position 1)에는 항상 널 디바이스 (null device)가 위치하지만, 사실 이 디바이스는 그랙픽 명령문을 전혀 실행하지 않습니다.

dev.next()
dev.prev()

리스트 상에서 현재 디바이스 보다 각각 (순서상) 앞이나 뒤에 위치한 그래픽 디바이스들의 개수와 이름을 보여주는 명령문.

dev.set(which=k)

디바이스 리스트 상 k 번째에 위치한 그래픽 디바이스를 현재 디바이스로 지정하기위해 사용하는 명령문. 새로 지정된 디바이스의 숫자와 이름을 출력합니다.

dev.off(k)

디바이스 리스트 상 k 번째 그래픽 디바이스를 종료시킵니다. postscript 와 같은 몇몇 디바이스의 경우, 디바이스의 종류에 따라 이 명령문은 해당 파일을 즉시 출력하거나 또는 나중에 출력하기 위해 해당 파일을 제대로 종료하는 것으로 실행됩니다.

dev.copy(device, …, which=k)
dev.print(device, …, which=k)

k 번째 디바이스를 복사(copy)하는 명령문. 여기서 디바이스 (device)포스트 스크립트(postscript) 같은 하나의 디바이스 함수를 의미하며, 필요할 경우 ‘’ 부분에 인수를 입력하여 사용할 수도 있습니다. dev.print도 비슷하게 사용되지만, 이 함수는 디바이스를 복사(copy)한 후 바로 종료시키므로, 하드 카피로 출력과 같은 명령을 즉시 실행하게 됩니다.

graphics.off()

널 디바이스(null device)를 제외한 리스트 상의 모든 그래픽 디바이스들을 종료합니다.


12.7 Dynamic graphics

R은 다이나믹(dynamic) 또는 대화형(interactive) 그래픽을 위한 빌트인(built-in) 기능을 제공하지 않습니다. (e.g. 포인트 덩어리(point clouds)를 회전시킨다거나, 포인트들을 “색칠하는 (brushing)” (대화형으로 포인트들을 하일라이팅하는,interactively highlighting points) 것 등등). 하지만, Swayne, Cook과 Buja가 개발한 GGobi 시스템에서는 이런 기능을 사용할 수 있습니다.

http://www.ggobi.org/

또 R에서는, 아래의 rggobi 패키지를 설치하여 이러한 그래픽 기능들을 사용할 수 있습니다.

또한, rgl 패키지는 3D plots에서, 좀 더 구체적으로 plot 의 표면(surfaces)에서, 대화형(interactive) 작업을 지원합니다.


13 Packages (패키지)

R의 모든 함수들과 데이터셋들은 패키지 (packages)안에 저장되어 있습니다. 따라서, 어떤 패키지가 로드(loaded)되었을 때만 패키지 안의 내용물들을 사용할 수 있습니다.이러한 패키지 시스템은 효율성(efficiency)과 개발자의 편의 (to aid package developers)라는 장점을 가집니다: 전체 리스트를 사용할 때 보다 메모리의 사용량이 적고, 필요한 내요을 검색하는 데도 훨씬 적은 시간이 걸린다는 점에서 효율적이며, 다른 코드와 같은 이름을 사용하게 되는 것(name clashes with other code)을 자연스럽게 방지하는 역할도 있으므로 패키지 개발자의 편의를 고려했다고 볼 수 있습니다. 패키지를 개발하는 과정에 대해서는 Creating R packages in Writing R Extensions를 살펴보시길 바랍니다.여기에서 우리는 사용자 측면에 대해서만 이야기할 것입니다.

어떤 패키지들이 여러분이 사용중인 R 프로그램(사이트, site)에 설치되어 있는지 알고싶다면, 인자의 입력 없이 다음의 함수를 사용하시면 됩니다.

> library()

특정한 하나의 패키지를 로드(load)하기 위해서는(예를 들면, Davison & Hinkley (1997)에 사용된 함수들이 포함되어 있는 boot를 사용하고 싶다고 가정합시다), 아래와 같은 명령어를 입력하면 됩니다.

> library(boot)

인터넷을 사용할 수 있다면, install.packages()update.packages() 함수들을 이용하여 패키지를 설치하거나 업데이트 할 수 있습니다. (윈도우즈와 RAqua GUI에서는 Packages 메뉴를 통해 이러한 작업을 실행할 수도 있습니다. see Installing packages in R Installation and Administration)를 참고하시길 바랍니다.)

현재 로드되어 있는 패키지들을 확인하고 싶다면 아래의 함수를 입력하여

> search()

검색 리스트(search list)를 확인할 수 있습니다.일부 패키지들은 로드되어있다고 하더라도 검색 리스트에서 보이지 않을 수도 있습니다.(여기에 대해서는 see ‘Namespaces’를 찾아보시길 바랍니다): 이러한 패키지들은 다음의 명령어를 사용하면 확인이 가능합니다.

> loadedNamespaces()

설치된 패키지에서 사용가능한 모든 도움말(help) 주제의 목록을 확인해보고 싶다면 아래의 명령어를 사용하시기 바랍니다.

> help.start()

이 명령어로 HTML 도움말 시스템(help system)이 시작되며, Reference 섹션에서 패키지 목록을 찾으시면 됩니다.


13.1 표준 패키지들 (Standard packages)

표준(또는 기본 (base)) 패키지들은 R 소스코드(source code)에서 매우 중요한 부분을 차지합니다.이 표준 패키지들은 R이 작동할 수 있도록하는 기본 함수들(basic functions)은 물론이고, 데이터셋, 표준 통계분석 및 (앞부분에서 설명된) 그래픽 함수들로 구성되어 있습니다. 이러한 표준 패키지들은 R 설치시에 자동으로 따라 옵니다. 모든 표준패키지 목록을 보고싶으시면 다음을 참조하세요. See R packages in R FAQ.


13.2 사용자-기여 패키지(Contributed packages)와 CRAN

There are thousands of contributed packages for R, written by many different authors. Some of these packages implement specialized statistical methods, others give access to data or hardware, and others are designed to complement textbooks. Some (the recommended packages) are distributed with every binary distribution of R. Most are available for download from CRAN (https://CRAN.R-project.org/ and its mirrors) and other repositories such as Bioconductor (https://www.bioconductor.org/) and Omegahat (http://www.omegahat.org/). The R FAQ contains a list of CRAN packages current at the time of release, but the collection of available packages changes very frequently.


13.3 네임스페이스 (Namespaces)

패키지들은 네임스페이스(namespaces)라는 것을 가질 수 있으며, 현재 datasets 패키지를 제외한 모든 기본 (base)과 권장(recommended ) 패키지들은 이 네임스페이스를 가지고 있습니다. 네임스페이스는 크게 다음의 세가지 역할을 수행합니다:첫째, 패키지 작성자가 내부적 사용만을 목적으로 개발한 함수들과 데이터들을 숨길 수 있도록 합니다. 둘째, 사용자나 (혹은 다른 패키지 작성자)가 해당 패키지에서 사용중인 함수명과 같은 이름의 함수를 사용하고자 할때, 같은 이름의 두 함수가 충돌하여 작동이 중단(breaking)되는 것을 방지합니다.마지막으로 특정 패키지 내의 하나의 객체(object)를 지칭하는 또다른 방법을 제시합니다.

예를 들면, t()는 R에서 행렬을 전치(transpose)하는 함수 입니다. 그러나, 사용자들 중에는 t라는 같은 이름을 갖는 자신만의 고유한 함수를 정의하고 싶은 사람도 있을 것입니다.이때 네임스페이스(namespaces)는 사용자 정의 함수가 우선권을 갖게 되어 행렬을 전치하기 위해 t()함수를 사용할 수 없게 되는 일이 없도록 방지합니다.

네임스페이스와 함께 사용되는 두개의 연산자들(operators)이 있습니다. 하나는 더블콜론(double-colon) 연산자 ::로, 특정 네임스페이스에 정의된 함수(definitions)들을 선택합니다.위의 예제를 다시 이용하면, 전치함수는 base 패키지 안에 정의되어 있기 때문에, 언제라도 base::t로 불러내는 것이 가능합니다.용할 수 있습니다. 하지만, 오직 패키지에서 내보내진(exported) 함수들만이 이런 식으로 사용될 수 있습니다.

트리플-콜론(triple-colon) 연산자 :::가 R 코드 내에서 사용되는 경우가 있습니다: 이 연산자는 더블-콜론 연산자와 비슷한 기능을 수행하지만, 숨겨진 객체(hidden objects)에 대해서도 접근할 수 있다는 점에서 차이가 있습니다.그러나, 여러개의 패키지들을 대상으로 검색할 수 있는, getAnywhere() 함수가 더 선호되는 경향이 있습니다.

패키지들은 서로 상호의존적(inter-dependent)이라, 하나를 로딩할 때 자동으로 다른 패키지들을 함께 로딩할 수 있습니다. 위에서 설명한 콜론 연산자들은 사용할 때도 관련있는 패키지들이 자동 로딩 됩니다.네임스페이스를 가진 패키지들이 자동 로드로 실행되면, 이들은 검색목록(search list)에 추가되지는 않습니다.


14 운영체제의 기능들에 대한 접근

R은 실행 중인 운영 체제를 이용할수있는 꽤 광범위 한 시설을가지고 있습니다: 이것은 R이 스크립트 언어로 사용될수 있고, R 자체가 그 능력을 십분 활용하고 있습니다. 예: 패키지 설치.

R 자체의 스크립트가 모든 플랫폼에서 작동 할수있어야 하기 때문에, 스크립팅 시설들이 플랫폼에 제한되지않게 가능한한 독자적으로 만들기위하여 상당한 노력이 들어갔습니다.


14.1 파일 및 디렉터리

파일및 디렉터리를 조작할수있는 함수는 많이있습니다. 좀 더 보편적으로 쓰이는 함수들 몇가지를 여기에서 설명하겠습니다.

비어있는 파일이나 디렉터리를 만들고 싶은 경우 file.create 이나 dir.create 를 사용합니다. (이 함수들은 POSIX utilities 의 touchmkdir 과 유사합니다.) R 세션 디렉터리에서 임시적으로 만든 파일이나 디렉터리일 경우 tempfile 을 참조 하십시요.

파일을 삭제할 때 file.remove 이나 unlink 를 사용할수 있습니다: 디렉터리 트리도 같이 삭제 시키고 싶은 경우 unlink 를 사용 하면 됩니다.

디렉터리 리스트 출력을 원할경우 list.files (dir 로도 사용가능) 이나 list.dirs 를 사용합니다. 이 함수들은 정규 표현식 (regular expression) 을 사용해 파일들을 찾을 수 있습니다: 와일드 카드를 사용할경우 Sys.glob 를 사용합니다.

file.info를 사용하여 filepath (예로 파일이나 디렉터리를 포함함) 에 있는 많은 양식의 정보들을 찾을수 있습니다.

파일이 ’존재’하는지 (파일이 파일 시스템에 존재하지만 현재 사용자에게 보이지 않는 경우도 있습니다) 확인하는 몇 가지 방법이 있습니다. 다양한 버전의 file.exists, file.access 그리고 file_test 함수들이 있습니다: 셸 스크립팅에 익숙한 분들을 위한 예로 file_test 는 POSIX test 명령어의 한 버전 입니다.

R 의 file.copy 라는 함수는 POSIX 명령어인 cp 의 유사체 입니다.

file.choose 를 사용하여 파일을 선택하는 작업을 대화 형으로 수행 할 수 있습니다: 윈도우즈 포트는 더 다양한 기능을 갖은 choose.fileschoose.dir 함수들을 가지고 있으며, tcltk 패키지에 유사한 함수들이 있습니다 : tk_choose.filestk_choose.dir.

file.showfile.edit 과 같은 함수들은, 만약 콘솔 (예로 윈도우즈에서 RGui나 OS X에서 R.app)을 사용중일 경우, 콘솔의 기능을 사용하여 R 포트에 적절한 방법으로 하나 이상의 파일을 표시및 편집합니다.

파일 시스템에 있는 links 를 일부 지원 하고 있습니다: file.linkSys.readlink를 참조하십시오.


14.2 Filepaths

몇 가지 예외를 제외하고, R 은 filepaths를 조작할때 기본 운영체제의 기능에 의존합니다. 어떤 면에서는 운영체제에 의존하게 허락되있고. 이것은 운영체제의 버전까지도 포함됩니다. 운영체제가 filepaths를 해석하는 방법에 대한 POSIX 표준이있습니다, 그리고 많은 R 사용자들이 POSIX 표준에 대한 준수를 가정하지만, 윈도우즈는 준수함을 제기하지 않고있으며, 다른 운영체제들도 완전히 준수하지는 않을 수 있습니다.

다음은 filepaths 에 관해서 발생 된 몇 가지 문제들 입니다.

basenamedirname 함수들을 사용하여 file path의 부분을 선택할수 있습니다: 구성 요소들을 이용하여 file path를 만들때 권장되는 방법은 file.path입니다. pathexpand 함수는 (현재 사용자의, 그리고 아마도 다른 사용자들의) 홈 디렉토리에 대한 값을 대체하여 ’틸드 확장’을 할수있게 합니다.

링크가 들어있는 파일 시스템일 경우, 하나의 파일이 많은 filepaths로 불려질수 있습니다. normalizePath 함수로 정식 filepath를 찾을 수 있습니다.

윈도우즈는 긴 파일 이름 및 짧은 (’8.3’) 파일 이름의 컨셉트를 갖고 있습니다: normalizePath 는 긴 파일 이름을 사용 하여 path의 절대 값을 출력하고 shortPathName은 짧은 이름을 사용는 버전을 출력 합니다. 후자는 공백을 포함 하지 않고 구분 기호로 백슬래시를 사용 합니다. 그래서, 때로는 R에서 이름을 export 하는 데 유용합니다.

파일 사용 권한에 관련된 주제입니다. R는 owner/group/all 에 대 하여 read/write/execute 권한의 POSIX 컨셉트를 지원하지만 파일 시스템은 부분적으로만 지원됩니다 (그래서 윈도우즈에만 관련된 예로 (R 세션을 실행 하는 계정에서) read-only 파일이 인식이 됩니다). 액세스 제어 목록 (Access Control Lists - ACLs)이 여러 파일 시스템에 사용 되고 있지만 합의된 표준이 없고 R역시 그 목록들을 제어할 수 있는 시설이 없습니다. 사용 권한을 변경 하려면 Sys.chmod를 사용하면 됩니다.


14.3 시스템 명령어

systemsystem2 함수들은 시스템 명령을 호출하고 선택적으로 출력을 수집하는데 사용됩니다. system2는 좀 더 일반적이지만, 그것의 주요 장점은 그것을 사용하는 크로스 플랫폼 코드를 작성하기가 더 쉽다는 것입니다.

system 은 윈도우즈에서 다른 운영체제들과 다르게 작용합니다 (이것과 같은 이름의 API C 명령이 이작업을 하기 때문입니다) . 다른 곳에서 이 함수는 명령을 실행하는 쉘을 호출합니다: R 의 윈도우즈 포트에서 쉘을 호줄 하려면 shell 함수를 사용합니다.

운영 체제가 명령을 포함하고 있는지 확인하려면, 크로스 플랫폼 방식으로이 작업을 수행하려고하는 Sys.which 를 사용합니다 (불행하게도 이것은 운영체제의 표준 서비스가 아닙니다).

shQuote 함수는 사용하고있는 운영체제 내에서의 명령을 위하여 필요에 따라 filepaths를 인용합니다.


14.4 압축과 아카이브 (archive)

R 의 최신 버전은 종종 투명하게, 압축 파일을 읽고 쓸 수있는 광범위한 시설들이 있습니다. R 에서 파일을 읽는 작업은 연결 (connections)file 함수에 의해 대부분 수행 됩니다. file 함수는 파일 (또는 URL)의 연결을 열어줄때 사용하고, 파일의 ’magic’ 헤더로 부터 사용된 압축방식을 식별할수도 있습니다.

압축방식 중 지원된지 가장 오래된 방식은 gzip 압축이고 이것은 적합하고 일반적인 절충안으로 남아있습니다. 예전 리눅스의 compress 유틸리티로 압축된 파일들 또한 읽어질수 있지만 이런 경우는 드물어 지고 있습니다. 두 가지 다른 압축 방식으로 bzip2xz 유틸리티들이 이용될수 있습니다. 이 방식들은 보통 더 높은 압축률을 이루지만 (파일에 따라서 훨씬 더 높을 수도 있음) 느린 감압시간과 훨씬 더 느린 압축시간을 감수해야 합니다.

There is some confusion between xz and lzma compression (see https://en.wikipedia.org/wiki/Xz and https://en.wikipedia.org/wiki/LZMA): R can read files compressed by most versions of either.

파일 아카이브란 파일들을 수집한 단일의 파일로, R 패키지들을 배포할때 사용되듯이, ’tarballs’ 과 zip 파일들이 가장 일반적으로 사용됩니다. R 은 이 두 가지 파일형태를 등재할수도 풀수도 있습니다 (untarunzip 함수 참조), 그리고 두 가지 형태를 모두 생산할수도 있습니다 (zip 같은 경우 외부 프로그램의 도움이 있어야 합니다).


Appendix A A sample session

다음 세션(session)은 R 환경(environment)의 일부 기능을 처음 접하는 사용자에게 소개할 목적으로 준비되었습니다. 처음에는 시스템의 많은 기능들이 익숙하지 않고 혼란스러울 수 있으나, 이러한 불편함을 곧 사라지게 될 것입니다.

사용자의 플랫폼에 맞추어 R을 올바르게 실행하도록 합니다 (see Invoking R (R을 실행하기))

R 프로그램이 배너와 함께 시작됩니다.

(혼돈을 피하기 위해서 R 코드를 표시할 때 왼쪽에 있는 프롬프트는 표시하지 않습니다.)

help.start()

사용자의 기계에서 이용이 가능한 인터넷 브라우저를 이용하여 HTML 인터페이스를 가진 온라인 도움말을 시작합니다. 마우스를 이용하여 어떻게 이용하는 것인지 간단히 살펴보시길 바랍니다.

다음의 내용들을 실습하기 위하여 도움말 창을 작게 만들어 놓습니다.

x <- rnorm(50)
y <- rnorm(x)

이것은 정규분포로부터 발생시킨 50개의 난수를 벡터 xy에 저장한 것입니다.

plot(x, y)

평면공간에 xy의 좌표로 이루어진 점들을 플랏해봅니다. 그패픽 창이 자동으로 나타나는 것을 볼 수 있습니다.

ls()

R 작업공간(workspace)에 어떤 R 객체들이 있는지 확인해봅니다.

rm(x, y)

더 이상 사용하지 않는 객체들을 작업공간으로부터 제거합니다.

x <- 1:20

x = (1, 2, …, 20)를 생성합니다

w <- 1 + sqrt(x)/2

표준편차(standard deviation)의 가중치(weight)를 생성합니다.

dummy <- data.frame(x=x, y= x + rnorm(x)*w)
dummy

xy의 두 개의 열을 가지는 데이터프레임(data frame)을 생성하고, 이를 살펴봅니다.

fm <- lm(y ~ x, data=dummy)
summary(fm)

단순 선형회귀(simple linear regression)을 적합합니다. 틸다표시 좌측에 있는 y에 관하여, 우리는 yx에 의존한다는 것을 모델한 것입니다.

fm1 <- lm(y ~ x, data=dummy, weight=1/w^2)
summary(fm1)

우리는 표준편차를 알고 있기 때문에, 가중회귀(weighted regression)분석을 수행합니다.

attach(dummy)

데이터프레임 내에 있는 열들을 일반적인 변수와 같이 접근할 수 있도록 해주는 것입니다.

lrf <- lowess(x, y)

비모수 국지회귀함수(nonparametric local regression)를 수행합니다.

plot(x, y)

일반적인 방법으로 xy를 플랏해 봅니다.

lines(x, lrf$y)

그래프에 회귀분석으로부터 나온 결과를 이용하여 회귀선을 추가합니다.

abline(0, 1, lty=3)

그래픽에 기울기가 1이고 절편이 0인 회귀선을 표시합니다.

abline(coef(fm))

가중치없이 수행한 회귀모형(unweighted regression)으로부터 얻은 회귀계수들을 이용하여 회귀선을 표시합니다.

abline(coef(fm1), col = "red")

Weighted regression line.

detach()

탐색경로(search path)로부터 데이터프레임을 제거합니다.

plot(fitted(fm), resid(fm),
     xlab="Fitted values",
     ylab="Residuals",
     main="Residuals vs Fitted")

이분산성(heteroscedasticity)을 확인하기 위해서 표준회귀 진단플랏(standard regression diagnostic plot)을 그립니다. 이를 볼 수 있나요?

qqnorm(resid(fm), main="Residuals Rankit Plot")

비대칭도(skewness), 첨도(kurtosis), 그리고 이상치(outliers)를 찾기 위해서 정규스코어플랏(normal score plot)을 이용해 봅니다. (실제로는 이 문제에 대해서 별로 유용하지 않습니다).

rm(fm, fm1, lrf, x, dummy)

Clean up again.

다음 섹션에서는 Michelson이 빛의 속도를 측정하기 위해서 사용했던 실험으로부터 모은 데이터를 이용해 보도록 하겠습니다. 이 데이터셋은 morley라고 객체명을 입력하면 이용이 가능하지만, 여기에서는 read.table 함수의 사용법을 알아보기 위해서 직접 데이터를 불러보도록 하겠습니다.

filepath <- system.file("data", "morley.tab" , package="datasets")
filepath

시스템내에 데이터 파일이 존재하는 위치에 대한 파일경로를 얻습니다.

file.show(filepath)

꼭 해보지 않아도 되지만, 파일의 내용을 살펴봅니다.

mm <- read.table(filepath)
mm

Michelson 데이터를 데이터프레임의 형식으로 읽어들인 뒤, 이를 확인해 보도록 합니다. 이 데이터셋은 Expt 변수에 5가지 종류의 실험정보를 저장했고, Run 변수에 종류별로 각각 20번씩 실험되었다는 정보를 가지고 있음을 보여줍니다. 그리고 sl 변수에 각 조건별 빛의 속도가 입력되어 있음을 알 수 있습니다.

mm$Expt <- factor(mm$Expt)
mm$Run <- factor(mm$Run)

ExptRun 변수들에 대한 데이터형을 요인(factor)로 변경합니다.

attach(mm)

데이터프레임을 포지션 3 (기본값)에서 볼 수 있도록 합니다.

plot(Expt, Speed, main="Speed of Light Data", xlab="Experiment No.")

박스플랏(boxplot)을 이용하여 5가지 종류의 실험들을 서로 비교해보도록 합니다.

fm <- aov(Speed ~ Run + Expt, data=mm)
summary(fm)

‘runs’와 ‘experiments’를 요인으로 놓은 상태에서 랜덤마이즈된 블락(randomized block) 분석을 합니다.

fm0 <- update(fm, . ~ . - Run)
anova(fm0, fm)

‘runs’를 제외한 모델 (sub-model)을 이용하여 적합한뒤, 일반적인 분산분석(analysis of variance)와 비교를 해봅니다.

detach()
rm(fm, fm0)

다음 분석으로 넘어가기 전에 불필요한 객체들을 삭제합니다.

이제 컨투어(contour)와 이미지(image) 플랏이라는 그래픽 기능에 대해서 알아보도록 합니다.

x <- seq(-pi, pi, len=50)
y <- x

x는 구간 [-pi\, pi]을 50등분한 값들을 가진 벡터입니다. the interval [-pi\, pi]. 벡터 y는 벡터 x와 동일합니다.

f <- outer(x, y, function(x, y) cos(y)/(1 + x^2))

fx가 행이고, y가 열인 정방행렬입니다. 이 행렬의 구성요소는 x의 구성요소와 y의 구성요소를 하나의 짝을 이루도록 하여 함수 cos(y)/(1 + x^2)를 적용하여 얻은 값으로 얻어지게 됩니다.

oldpar <- par(no.readonly = TRUE)
par(pty="s")

현재 저장되어 있는 플랏팅 모수 (parameters)들을 보관한 뒤, 플랏팅 영역 (plotting region)을 “square”로 설정합니다.

contour(x, y, f)
contour(x, y, f, nlevels=15, add=TRUE)

f의 컨투어 맵(contour map)을 생성하고, 15개의 컨투어 레벨(등고선)을 보여지도록 합니다.

fa <- (f-t(f))/2

faf의 “asymmetric part”(비대칭 부분)입니다 (여기에서 t()는 행렬의 전치를 의미합니다).

contour(x, y, fa, nlevels=15)

컨투어 플랏을 생성합니다.

par(oldpar)

이전에 보관한 그래픽 파라미터들을 원래대로 복구시킵니다.

image(x, y, f)
image(x, y, fa)

이미지 플랏을 생성합니다.

objects(); rm(x, y, f, fa)

어떤 객체들이 워크스페이스에 있는지 확인한 뒤, 다음 분석을 수행하기 전에 불필요한 객체들을 제거합니다.

R에서는 복소수 연산(complex arithmetic) 또한 가능합니다.

th <- seq(-pi, pi, len=100)
z <- exp(1i*th)

1i는 복소수(complex number) i를 나타냅니다.

par(pty="s")
plot(z, type="l")

허수(imaginary part)와 실수(real part)부분을 플랏합니다. 반드시 원의 모양이어야 합니다.

w <- rnorm(100) + rnorm(100)*1i

반지름이 1인 단위 원(unit circle) 안 쪽 부분으로부터 우리는 샘플링을 한다고 가정합니다. 한 가지 방법은 표준정규분포가 실수와 허수부분에 적용된 복소수를 취하는 것입니다.

w <- ifelse(Mod(w) > 1, 1/w, w)

단위 원 밖에 놓여 있는 값들은 역수를 취하도록 합니다.

plot(w, xlim=c(-1,1), ylim=c(-1,1), pch="+",xlab="x", ylab="y")
lines(z)

단위 원(unit circle)내에 모든 점들이 있음을 알 수 있지만, 이들이 균일하게 분포(uniform distribution)된 것이 아님을 알 수 있습니다.

w <- sqrt(runif(100))*exp(2*pi*runif(100)*1i)
plot(w, xlim=c(-1,1), ylim=c(-1,1), pch="+", xlab="x", ylab="y")
lines(z)

두 번째 방법으로는 균일분포(uniform distribution)를 이용하는 것입니다. 이것은 디스크에 점들이 균등하게 퍼져있는 것처럼 보여야 합니다.

rm(th, w, z)

Clean up again.

q()

R 프로그램을 종료합니다. 이때, R 작업공간(workspace)를 저장하고 싶은지에 대해서 물어보게 될 것입니다. 기초사용법에 대한 설명을 목적으로 한 세션이므로 꼭 저장하고 싶지는 않을 것입니다.


Appendix B Invoking R (R을 실행하기)

Windows 또는 Mac OS X에서 R을 이용하는 사용자들은 특정 운영체제에 관한 설명이 되어 있는 섹션을 먼저 읽어보시길 바랍니다. 그러나, 명령어를 이용한 사용 또한 지원되고 있습니다.


B.1 Invoking R from the command line

UNIX 또는 Windows 환경에서 명령어를 이용하여 작업을 할때, 명령어 ‘R’은 아래와 같은 형식으로 R 프로그램을 실행하는데 사용될 수 있습니다.

R [options] [<infile] [>outfile],

또한, R CMD라는 인터페이스를 통하여 다양한 R 도구들 (즉, R의 문서형식으로 되어 있는 파일들을 프로세싱하거나 애드온 패키지들을 조작하는데 사용하기 위한 것들)을 직접 호출하지 않고도 사용할 수 있습니다.

Windows 커맨드 라인에서는 R보다는 Rterm.exe를 이용하는 것을 선호합니다.

환경 변수(environment variable) TMPDIR이 지정되지 않았거나, 임시 파일과 디렉토리 생성을 하는데 이용되는 공간을 올바르게 지정했는가에 대해서 확인하는 것이 필요합니다.

대부분의 옵션들은 R 세션의 시작과 끝에서 어떤 것들을 해야하는가를 조절하게 됩니다. 스타트업 메카니즘 (startup mechanism)은 다음과 같습니다 (더 많은 정보를 ‘Startup’이라는 주제와 관련한 온라인 도움말에서 찾아볼 수 있으며, 일부 Windows와 관련된 내용들은 아래의 섹션에서 찾아볼 수 있습니다).

추가적으로 R 처리과정에 이용되는 메모리를 조절하는 옵션들이 있습니다. (더 많은 정보를 원하신다면 ‘Memory’와 관련된 온라인 도움말을 살펴보시길 바랍니다). R에 의하여 사용되는 메모리를 크기를 조절하고자 하지 않는다면 사용자는 이들을 사용해야 할 필요는 없습니다.

R은 다음과 같은 명령어 옵션들을 제공합니다.

--help
-h

표준 출력(standard output)으로 짧은 도움말 메시지를 보여주고 종료합니다.

--version

표준 출력(standard output)으로 버전정보를 표시해주고 종료합니다.

--encoding=enc

stdin 또는 콘솔로부터의 입력에 사용될 인코딩(encoding)을 지정합니다. 이것은 iconv에서 사용될 수 있는 알려진 인코딩이어야 합니다. 도움말 페이지를 참고하시길 바랍니다. (--encoding enc) 또한 사용될 수 있습니다.

RHOME

표준출력에 R “home directory” (홈디렉토리)의 경로를 보여주고 종료합니다. 사용자가 직접 작성하는 쉘 스크립트(shell script)와 도움말 페이지(man page)를 제외하고 실행이 가능한 파일들, 패키지 등 모두가 R이 설치되어 집니다.

--save
--no-save

R세션을 종료할때 데이터 셋들을 저장할 것인지에 대한 여부를 조절합니다.

--no-environ

환경변수를 설정하기 위한 어떠한 유저파일(user file)을 읽어들이지 않습니다.

--no-site-file

스타트업(startup)에서 사이트-와이드 프로파일 (site-wide profile)을 읽어들이지 않습니다.

--no-init-file

스타트업(startup)에서 사용자의 프로파일을 읽어들이지 않습니다.

--restore
--no-restore
--no-restore-data

스타트업(startup)할때 R이 시작된 디렉토리내에서 .RData의 형식으로 저장되어진 이미지들 복구할 것인지를 조절합니다. 기본값은 복구하는 것입니다. (--no-restore는 좀 더 세부적인 --no-restore-*과 같은 옵션들 모두를 의미합니다)

--no-restore-history

R이 시작된 디렉토리내에 일반적으로 .Rhistory로 되어 있는 작업기록파일 (history file)을 스타트업 (startup)할때 복구할 것인지를 조절합니다. 이 파일은 환경변수 R_HISTFILE에 의해서 지정될 수도 있습니다. 기본값은 복구하는 것입니다.

--no-Rconsole

(Windows에만 적용되는 옵션입니다). 이는 스타트업시에 Rconsole 파일을 로딩하지 못하게 합니다.

--vanilla

--no-save, --no-environ, --no-site-file, --no-init-file, --no-restore를 모두 한데 묶은 것입니다. Windows상에서는 이 옵션은 또한 --no-Rconsole을 포함합니다.

-f file
--file=file

(Rgui.exe에 적용되지 않습니다). file로부터 입력을 가져옵니다: ‘-’은 stdin을 의미합니다. --save가 지정되지 않았다면 --no-save를 의미하게 됩니다. Unix와 같은 환경에서는 쉡 메타문자(shell metacharacters)는 file내에서 사용을 피해야 합니다. (그러나, R 2.14.0 부터 공백(spaces)들이 허용됩니다).

-e expression

(Rgui.exe에서는 사용할 수 없습니다). expression을 한줄의 입력라인 (input line)으로 이용하세요.하나 또는 그 이상의 -e 옵션들이 사용될 수 있으나, -f 또는 --file과는 함께 사용할 수 없습니다. --save가 지정되어 있지 않다면 --no-svae을 의미하게 됩니다. (이러한 방식으로 expression 부분에 들어갈 수 있는 최대 길이는 10,000 바이트 입니다. 공백 또는 쉘 메타문자들을 포함하는 expressions들은 따옴표를 사용해야 할 필요가 있습니다)

--no-readline

(UNIX에서만 사용됩니다) readline을 통해서 명령어줄(command-line)을 편집하는 것을 끕니다. 이것은 ESS(“Emacs Speaks Statistics”) 패키지를 이용하여 Emacs상에서 R을 실행할 때 유용합니다. 더 많은 정보를 원하시면 See The command-line editor (명령어라인 편집기)를 살펴보시길 바랍니다. 명령어라인 편집은 기본적으로 대화식으로 사용합니다. (--interactive를 살펴보세요). 이 옵션은 또한 틸데확장(tilde-expansion)에 영향을 미칩니다. 이것에 대해서는 path.expand에 대한 도움말을 살펴보시길 바랍니다.

--min-vsize=N
--min-nsize=N

고급사용자들에게만 권장됩니다. 바이트단위의 벡터 힙(vector heap)과 cons cells (numbers)에 대한 가비지 컬렉션 (garbage collection)에 대한 초기 트리거 크기 (initial trigger sizes)를 설정합니다. 접미사 ‘M’은 메가바이트 (megabytes)또는 수백만개의 셀 (millions of cells)을 지정합니다.기본값은 6Mb 와 350k 입니다.

--max-ppsize=N

N위치만큼 해당하는 포인터 프로텍션 스택(pointer protection stack)의 최대 크기를 지정합니다. 기본값은 10000이지만, 대규모의 복잡한 연산을 위하여 증가될 수 있습니다. 현재의 최대값은 100000입니다.

--max-mem-size=N

(Windows에만 해당합니다) R객체들과 작업영역을 위해 사용되는 메모리의 양의 한계를 지정합니다. 기본적으로 이는 R 32-비트를 기준으로 물리적인 RAM의 크기보다 작은 1.5Gb25로 지정되어 있습니다. 이는 반드시 32Mb와 Windows의 해당버전에서 허용하는 최고치 사이어야 합니다.

--quiet
--silent
-q

실행 초기에 보여지는 카피라이트(copyright)와 환영 메시지를 보여주지 않습니다.

--slave

R를 가능한 조용히 실행합니다. 이 옵션은 R을 이용하여 연산을 수행하는 프로그램을 지원하기 위한 목적으로 존재합니다. --quiet--no-save를 의미합니다.

--interactive

(UNIX에서만 사용가능합니다) 입력의 방향이 설정되어 있을지라도 R이 대화식으로 사용되도록 하게 합니다. (기본적으로 stdin이 터미널(terminal) 또는 pty에 연결되어 있을 때 R은 대화식으로 실행되도록 되어 있습니다). 만약 --interactive이 주어져 있을지라도, -e, -f, 또는 --file은 비대화식 모드로 사용하게 됩니다.

Note that this does not turn on command-line editing.

--ess

(Windows만 가능합니다) 명령어를 이용한 에디터 사용없이 대화식으로 사용할 수 있는 기능을 포함하여 ESS 내에서 R-inferior-mode에 의해서 사용할 수 있도록 Rterm을 지정합니다.

--verbose

진행과정에 대한 정보를 출력하고, 특히 R의 옵션 verboseTRUE로 지정합니다. R 코드는 이 옵션을 이용하여 진단 메시지 (diagnostic message)의 출력을 조정하게 됩니다.

--debugger=name
-d name

(UNIX에서만 이용이 가능합니다). name이라는 이름의 디버거(debugger)를 통해 R을 실행합니다. valgrind와 최신버전의 gdb를 제외한 대부분의 디버거들에서, 추가적인 명령어 라인 옵션 (command line options)들이 무시되는 대신에 R이 실행될 때 디버거 내에서 실행이 가능합니다.

--gui=type
-g type

(UNIX에서만 이용가능합니다) 그래픽 사용자 환경으로서 type을 이용합니다 (이것은 대화식 기능의 그래픽 또한 포함합니다). 현재 type에서 사용가능한 값들은 기본적으로 ‘X11’이며, ‘Tcl/Tk’가 지원된다는 가정하에 ‘Tk’입니다. (back-compatibility를 위해서 ‘x11’과 ‘tk’도 사용될 수 있습니다).

--arch=name

(UNIX only) Run the specified sub-architecture.

--args

이 플래그(flag)는 커맨드라인의 남은 부분을 건너뛰도록 유도하는 것을 제외하면 다른 기능은 없습니다. commandArgs(TRUE)와 함께 값을 검색 또는 다시 불러오는데 유용합니다.

<’와 ‘>’를 이용하여 일반적인 방법으로 입력과 출력의 방향을 조절할 수 있으나, 라인의 길인에 대한 4095 바이트의 제한은 여전히 적용되게 됩니다. 경고와 에러메시들이 에러 채널인 stderr로 보내어지게 됩니다.

명령어 R CMD는 R과 함께 사용될 수 있는 유용한 도구들을 실행시키도록 해줍니다. 그러나 이것은 직접적으로 실행시키기 보다는 다음과 같은 일반적인 형식을 가집니다.

R CMD command args

여기에서 command는 도구의 이름이고 args는 그 도구에 넘겨지게 될 입력인자들을 의미합니다.

현재, 다음과 같은 도구들을 사용할 수 있습니다.

BATCH

R을 배치모드(batch mode)에서 실행시킵니다. R --restore --save와 추가적인 옵션들을 이용할 수 있습니다. (?BATCH를 참조하기 바랍니다).

COMPILE

(UNIX에서만 사용할 수 있습니다) R과 함께 사용할 수 있는 C, C++, Fortran … 파일들을 컴파일합니다.

SHLIB

다이나믹 로딩을 위하여 공유된 라이브러리 (shared library)를 빌드(build)합니다.

INSTALL

애드온(add-on) 패키지들을 설치합니다.

REMOVE

애드온(add-on) 패키지들을 제거합니다.

build

애드온(add-on) 패키지들을 빌드(build)합니다.

check

애드온(add-on) 패키지들을 체크(check)합니다.

LINK

(UNIX에서만 사용가능합니다) 실행가능한 프로그램을 생성하기 위하여 전처리 (front-end)입니다.

Rprof

Post-process R profiling files.

Rdconv
Rd2txt

Rd 포맷을 HTML, LaTex, 일반 텍스트, 그리고 예제들을 추출하는 등 다양한 포맷으로 전환합니다. Rd2txtRd2conv -t txt의 약식 표기입니다.

Rd2pdf

Rd 포맷을 PDF로 전환합니다.

Stangle

Sweave 문서로부터 S/R 코드를 추출합니다.

Sweave

Sweave 문서를 프로세스 합니다.

Rdiff

Diff R output ignoring headers etc

config

환경설정에 대한 정보 (configuration information)을 가져옵니다.

javareconf

(UNIX에서만 사용가능합니다) Java 설정 변수들을 업데이트 합니다.

rtags

(UNIX에서만 사용가능합니다) C, R, 그리고 Rd 파일들로부터 이맥스 (Emacs)스타일의 태그 파일들을 생성합니다.

open

(Windows에서만 사용가능합니다) Windows의 파일연결(file association)을 이용하여 파일을 엽니다.

texify

(Windows에서만 사용가능합니다) R 스타일 파일을 사용하는 (La)TeX 파일들을 프로세싱합니다.

Use

R CMD command --help

R CMD를 통하여 사용이 가능한 도구들의 각각에 대한 사용방법을 알고 싶을 때는 다음과 같이 입력하세요.

추가적으로 도구들에 의해 실행되는 어떠한 R 프로세스들에 영향을 미칠 수 있는 --arch=, --no-environ, --no-init-file, --no-site-file 그리고 --vanilla 옵션들을 RCMD 사이에 사용26할 수 있습니다. (여기에서 --vanilla--no-environ --no-site-file --no-init-file과 동일합니다.)그러나, R CMD 이 자체로는 어떠한 R 스타드업 파일들을 사용하지 않는다는 것을 알고 계셔야 합니다 (특히, 사용자 또는 사이트 Renviron 파일 모두 이용하지 않습니다). 그리고, BATCH를 제외한 이러한 도구들에 의해서 실행되는 R 프로세스들의 모두는 --no-restore를 사용합니다. 대부분은 --vanilla를 사용하고 R 스타트업 파일들을 작동시키지 않습니다. 현재 예외라고 할 수 있는 것들은 INSTALL, REMOVE, Sweave 그리고 (--no-site-file --no-init-file을 이용하고 있는) SHLIB 입니다. 절대경로 (absolute filepath)에 의해서 주어진 또는 해당경로상에 있는 어떠한 다른 실행가능한 cmd을 사용하기 위해서는 아래와 같이 사용합니다.

R CMD cmd args

이렇게 하는 것은 R 또는 ldd 또는 pdflatex와 같은 어떤 특정한 명령어가 수행되어져야 하는 환경을 동일하게 해주는데 유용합니다. Windows 상에서 cmd는 실행이 가능할 수도 있고 배치파일 (batch file)일수도 있으며, 만약 .sh 또는 .pl과 같은 확장자를 가진다면 적합한 인터프리터(interpreter)가 이들을 실행시키기 위해서 호출되어집니다.


B.2 Invoking R under Windows

Windows에서 R을 실행하는 방법은 두 가지가 있습니다. cmd.exe 또는 이보다 좀 더 많은 기능들을 가지고 있는 쉘과 같은 터미널을 보여주는 윈도우 내에서는 이전 섹션에서 설명한 방법들이 사용될 수 있는데, 이는 R.exe 또는 Rterm.exe를 실행하는 것입니다. 대화식으로 사용하기 위해서는 콘솔기반의 그래픽 사용자 환경인 Rgui.exe가 있습니다.

Windows 상에서 스타트업 방식은 UNIX와 유사하지만, ’home directory’ (홈디렉토리)에 대한 참조는 Windows상에서 항상 정의되는 것이 아니기 때문에 좀 더 명확히 정해줘야 합니다.환경변수(environment variable) R_USER을 정의하는 것은 홈디렉토리를 지정하는 것입니다.또한, 환경변수 HOME을 정의하는 것 역시 홈디렉토리를 정하는 것입니다.사용자가 조절할 수 있는 이 두 변수들이 설정되면, R은 홈디렉토리를 지정하는 시스템을 찾으려고 합니다. 제일먼저, Windows 개인 디렉토리 (일반적으로 Windows XP의 경우에는 C:\Documents and Settings\username\My Documents를 의미합니다)를 지정합니다.실패시에는 환경변수 HOMEDRIVEHOMEPATH가 지정하는 홈디렉토리를 사용하게 됩니다. 이 모든 과정이 실패할 경우에 홈디렉토리는 스타팅 디렉토리로 정해지게 됩니다.

환경변수 TMPDIR, TMP 혹은 TEMP가 결정되지 않거나, 이 둘 중 하나가 일시적인 파일 혹은 디렉토리 생성을 위한 유효한 공간을 지정하게 끔 설정해야 합니다.

환경변수들은 명령어 라인에서 ‘name=value’와 같은 형식으로 제공됩니다.

만약 어떠한 경우에라도 .RData로 끝나는 인자가 있다면, 이것은 불러오게 될 작업공간에 대한 경로로서 인식되어집니다.이것은 --restore를 의미하는 것이고, 주어진 이름을 가진 파일의 상위디렉토리에 대한 작업 디렉토리를 지정하는 것이기 때문입니다.(이러한 메카니즘은 드래그-앤-드랍(drag-and-drop)과 RGui.exe와 사용되는 파일연결(file association)을 위해 사용됩니다. 그러나, 또한 Rterm.exe를 위해 사용되기도 합니다. 만약 주어진 이름을 가진 파일이 존재하지 않는다면 이것은 작업디렉토리를 부모디렉토리가 있을경우에 지정하게 됩니다).

RGui.exe를 작동시킬때 다음과 같은 추가적인 명령어 옵션들이 이용가능합니다.

--mdi
--sdi
--no-mdi

Rgui가 하나의 주 윈도우 상에 여러 개의 작은 윈도우 창을 이용하는 MDI 프로그램 혹은 콘솔, 그래픽, 또는 페이저를 위한 다수의 최상의 윈도우들을 가진 SDI 어플리케이션으로 사용할 것인지를 조절합니다. 명령어라인을 이용한 설정은 사용자의 Rconsole 파일에 있는 설정을 덮어쓰게 됩니다.

--debug

Rgui내에서 “Break to debugger”라는 메뉴 항목을 이용할 수 있게 해주고, 커맨드 라인이 프로세싱되는 동안 디버거에게 브레이크를 작동시켜줍니다.

Windows에서 R CMD를 이용할 때 당신이 소유한 .bat, .exe, .sh 또는 .pl 파일들 또한 지정할 수 있습니다. 이것은 적합한 인터프리터 (즉, .pl파일은 Perl을 이용합니다)와 R_HOME, R_OSTYPE, PATH, BSTINPUTS, 그리고 TEXINPUTS를 포함하여 올바르게 지정된 여러가지의 환경변수들과 함께 실행될 것입니다. 예를들면, 당신의 경로에 latex.exe파일을 이미 가지고 있다면 아래와 같이 방법으로 TEXINPUTS에 추가되어 있는 R의 share/texmf 매크로를 이용하여 mydoc.tex에 대해서 LaTeX를 실행시킬 수 있습니다.

R CMD latex.exe mydoc

(안타깝게도, MiKTex LaTeX에서는 적용되지 않습니다. 그러나, R CMD texify mydoc은 작동할 것입니다.)


B.3 Invoking R under OS X

Mac OS X 상에서 R을 실행하는 방법에는 두가지가 있습니다. 첫 번째 서브섹션에서 설명된 방법처럼 Terminal.app 창을 이용하여 R을 작동하는 것입니다. 또 다른 방법은 당신의 시스템에 있는 Applications 폴더에 기본적으로 설치된 콘솔기반의 GUI (R.app)을 이용하는것입니다. 이것은 더블클릭이 가능한 Mac OS X 응용프로그램입니다.

Mac OS X에 있는 스타트업 프로시져는 유닉스의 것과 유사합니다. ‘home directory’ 는 R.framework 내부에 있지만, GUI내로부터 접근이 가능한 Preference 창에 있는 스타트업 디렉토이와 다르지 않다면 스타트업과 현재 작업디렉토리는 사용자의 홈디렉토리와 같이 지정됩니다.


B.4 Scripting with R

만약에 R 명령어들로 이루어진 foo.R라는 파일을 실행시키고자 한다면, R CMD BATCH foo.R를 사용하길 권장합니다. 만약 당신이 이를 일괄처리 (batch job) 작업으로서 또는 후순위 작업 (background job, 백그라운드 작업)를 하고자 한다면, 당신의 운영체제에 맞는 기능을 사용하길 바랍니다. 예를들면, 유닉스와 같은 운영체제들은 쉘상에서 R CMD BATCH foo.R&라고 입력하게 되면 후순위작업 (background job)이 실행되게 됩니다.

명령어 라인을 사용할때 추가적인 인자들을 이용하여 스크립트에 파미미터 (또는 입력해야 할 인자들)에 값을 넣어줄 수 있습니다. 예를들면 (어떤 쉘을 이용하는가에 따라 다르지만, 아래와 같이 큰 따옴표의 사용이 필요합니다).

R CMD BATCH "--args arg1 arg2" foo.R &

위에서 사용된 명령어 라인은 아래와 같은 방법으로 다시 확인할 수 있는 문자형 벡터로서 스크립트에 인자들을 넘겨줄 수 있습니다.

args <- commandArgs(TRUE)

이렇게 하는 것은 사용자가 직접 아래와 같이 Rscript에 인자들을 전달할 수 있는 더 간단한 방법입니다.

Rscript foo.R arg1 arg2

그리고 이렇게 하는 것은 (적어도 유닉스와 같은 환경 및 일부 Windows의 쉘상에서) 실행가능한 스크립트를 작성하는데 사용될 수 있습니다. 예를들면, 아래와 같습니다.

#! /path/to/Rscript
args <- commandArgs(TRUE)
...
q(status=<exit status code>)

만약에 runfoo라는 텍스트 파일에 입력하고, 이것을 chmod 755 runfoo라는 명령어를 이용하여 실행가능하게 만들어 준다면, 아래와 같이 실행도 가능합니다.

runfoo arg1 arg2

더 많은 옵션들을 알아보고 싶으시다면 help("Rscript")를 살펴보시길 바랍니다. 이것은 R의 결과물을 stdoutstderr에 작성합니다. 그리고 이것은 명령어를 실행시키는 쉘상에서 일반적인 방법으로 다른 방향으로 전환이 가능합니다.

만약 당신이 Rscript에 경로를 쉽게 변경하고자 하면, 이를 아래와 같이 경로를 적어두어야 합니다. (Windows를 제외한 경우 설치된 R의 일반적인 경우이지만 Mac OS X 사용자들은 아마도 /usr/local/bin 이라고 할 수도 있습니다).

#! /usr/bin/env Rscript
...

본(Bourne)과 bash(배쉬) 쉘상에서는 #! 메카니즘은 #! /usr/bin/env Rscript --vanilla와 같은 추가적인 인자의 사용을 허용하지 않습니다.

한 가지 고려해야 할 점은 stdin()이 무엇을 의미하는지 알아야 합니다. R 스크립트를 아래와 같이 작성하는 것은 매우 흔한일입니다.

chem <- scan(n=24)
2.90 3.10 3.40 3.40 3.70 3.70 2.80 2.50 2.40 2.40 2.70 2.20
5.28 3.37 3.03 3.03 28.95 3.77 3.40 2.20 3.50 3.60 3.70 3.70

여기에서 stdin()이란 기존의 사용방법을 허용하는 스크립트 파일 자체를 의미합니다. 프로세스의 stdin을 참조하고 싶다면, "stdin"file 커넥션과 같이 사용하시면 됩니다. 즉, scan("stdin", ...).

또다른 방법으로 실행가능한 스크립트 파일들을 만드는 방법들은 (François Pinard에 의해 제안된) 이곳의 문서와 같이 사용하는 것입니다.

#!/bin/sh
[environment variables can be set here]
R --slave [other options] <<EOF

   R program goes here...

EOF

그러나, 여기에서 stdin()은 프로그램 소스를 가리키며 "stdin"은 사용가능하지 않을 것입니다.

매우 짧은 길이의 스크립트는 -e 플래그를 이용하여 Rscript에 보낼 수도 있습니다.

유닉스와 같은 환경에서 foo.R와 같은 입력파일명은 반드시 공간을 포함해서도 안되며, 쉘의 메타문자 역시 포함해서는 안됩니다.


Appendix C The command-line editor (명령어라인 편집기)

C.1 Preliminaries

UNIX 상에서 컴파일을 위하여 R의 환경설정을 할때 GNU readline 라이브러리가 사용가능 할 때, 이전 명령어들의 기억기능(recall), 편집(editing), 그리고 재입력(resubmission) 기능을 허용하는 내재된 커맨드기반의 에디터가 이용됩니다. 다른 버전의 readline이 존재 할 수 있고, 이들이 내재된 커맨드 기반의 명령어에 의해서 사용될 수도 있습니다.보통 Mac OS X에서 이러합니다

스타트업 옵션 --no-readline을 이용하여 사용되지 않도록 할 수도 있습니다. (이렇게 하는 것은 ESS27를 사용할 때 유용합니다).

Windows 버전에서 R은 다소 간단한 형식의 커맨드라인 편집기능을 가지고 있습니다. GUI에서 ‘Help’ 메뉴에 있는 ‘Console’을 살펴보시고, Rterm.exe내에 있는 커맨드라인을 위한 파일 README.Rterm을 살펴보시길 바랍니다.

readline의 기능과 함께 R을 사용할 때, (아마도) 당신의 시스템에 있는 man readline 또는 info readline에 기술되어 있는 함수들과 아래에 기술된 함수들을 이용할 수 있습니다.

이들중의 많은 것들이 컨트롤 (Control)과 메타(Meta) 문자들을 사용합니다. Control-m과 같은 형식으로 컨트롤 문자들은 CTRL키를 누른 상태에서 m키를 누르는 것입니다.그리고 이것을 C-m이라고 표시합니다.Meta-b와 같이 메타문자들은 META28를 누른 상태에서 b를 누르는 것이며, 이는 M-b라고 씁니다.만약에 당신의 터미널이 활성화된 META키를 가지고 있지 않다면, 당신은 ESC를 사용하여 메타문자들을 입력할 수 있습니다.그러므로, M-b를 입력하기 위해서는, 당신은 ESCb라고 입력합니다.다음은 중요한 메타 문자들을 정리한 것입니다.

C.2 Editing actions

R 프로그램은 당신이 입력한 명령어 라인들에 대한 기록을 보관합니다. 이때 잘못 입력한 명령어도 보관이 되며, 기록상에 보관된 명령어들은 다시 불러올 수 있고, 필요하다면 변경하여, 새로운 명령어처럼 다시 사용될 수 있습니다. 이맥스 스타일(Emacs-style)의 명령어라인 편집환경에서는 당신이 입력하는 것들이 편집하는 명령어 속에 삽입되거나, 커서의 오른쪽에 있는 문자들을 변경하하기도 합니다. vi 모드에서는 ESC를 입력함으로서 문자가 입력되거나 삽입모드를 종료할 수 있습니다. (기본적으로는 이맥스 스타일이 사용되며, vi 모드에 대해서는 readline 문서를 확인하시길 바랍니다).

어떤 상황이던지 간에 RET키를 누르는 것은 명령어를 실행하도록 전달하는 것과 같습니다.

다른 편집 기능들은 아래의 표에 정리되어 있습니다.

커맨드라인 에디터에 대한 요약

커서의 상하이동을 통하여 명령어를 되부르기

C-p

이전에 사용한 명령어로 이동합니다 (히스토리 상에서 한 단계 뒤로 이동하는 것입니다).

C-n

다음 명령어로 이동합니다 (히스토리상에서 한 단계 다음으로 이동하는 것입니다).

C-r text

text를 포함하는 마지막 명령어를 찾습니다.

대부분의 터미널에서 C-pC-n를 이용하는 대신에 당신은 위쪽 또는 아래쪽 방향의 화살표를 이용하여 이를 이용할 수 있습니다.

커서를 좌우로 이동하여 할 수 있는 명령어들

C-a

명령어의 가장 처음으로 이동합니다.

C-e

라인의 끝으로 이동합니다.

M-b

한 단어 뒤로 이동합니다.

M-f

한 단어 앞으로 이동합니다.

C-b

한 문자 뒤로 이동합니다.

C-f

한 문자 앞으로 이동합니다.

대부분의 터미널에서는 당신은 C-bC-f를 이용하는 대신에 좌측 또는 우측 화살표를 이용할 수 있습니다.

편집 후 재실행하기

text

커서의 위치에 text 삽입합니다.

C-f text

커서의 위치 다음부분 부터 text를 추가합니다.

DEL

커서의 왼쪽에 위한 문자를 삭제합니다

C-d

커서의 바로 아래 있는 문자를 삭제합니다.

M-d

커서의 아래에 있는 위치하는 문자 이후의 모든 것을 삭제하고 “저장” 합니다.

C-k

커서의 위치로부터 명령어의 끝 부분까지 삭제한 뒤, “저장” 합니다.

C-y

마지막으로 저장된 텍스트를 이곳에 삽입니다.

C-t

다음 문자를 커서 아래에 있는 문자와 전치합니다.

M-l

단어의 남겨진 부분들을 소문자로 변경합니다.

M-c

단어의 남겨진 부분들을 대문자로 변경합니다.

RET

R에 명령어를 다시 전달합니다.

마지막 RET 키는 명령어 라인의 편집 시퀀스를 종료하는 것입니다.

Readline 키바인딩 (key binding)은 ~/.inputrc 파일을 통해서 일반적인 방법으로 조정될 수 있습니다. R 2.12.0 부터는 이러한 개인설정 (customization)은 R에 따라 조건적일 수 있습니다.

$if R
  "\C-xd": "q('no')\n"
$endif

Appendix D 함수 및 변수와 관련된 색인

Jump to:   !   %   &   *   +   -   .   /   :   <   =   >   ?   ^   |   ~  
A   B   C   D   E   F   G   H   I   J   K   L   M   N   O   P   Q   R   S   T   U   V   W   X  
Index Entry  Section

!
!: 논리형 벡터
!=: 논리형 벡터

%
%*%: Multiplication
%o%: 두 배열의 외적

&
&: 논리형 벡터
&&: Conditional execution

*
*: 벡터 연산

+
+: 벡터 연산

-
-: 벡터 연산

.
.: Updating fitted models
.First: 환경 설정하기
.Last: 환경 설정하기

/
/: 벡터 연산

:
:: Generating regular sequences (규칙성을 지닌 일련의 숫자들을 생성하기)
::: 네임스페이스 (Namespaces)
:::: 네임스페이스 (Namespaces)

<
<: 논리형 벡터
<<-: Scope (스코프)
<=: 논리형 벡터

=
==: 논리형 벡터

>
>: 논리형 벡터
>=: 논리형 벡터

?
?: 도움말 기능 사용하기
??: 도움말 기능 사용하기

^
^: 벡터 연산

|
|: 논리형 벡터
||: Conditional execution

~
~: 식(formulae)을 통한 통계모형의 정의

A
abline: Low-level plotting commands
ace: Some non-standard models
add1: Updating fitted models
anova: Generic functions for extracting model information
anova: ANOVA tables
aov: Analysis of variance and model comparison
aperm: 배열의 전치에 사용되는 일반화된 방법
array: array() 함수
as.data.frame: 데이터 프레임 생성하기
as.vector: 배열에 사용되는 결합함수 c()
attach: attach()와 detach()
attr: Getting and setting attributes (속성을 설정하고 확인하기)
attr: Getting and setting attributes (속성을 설정하고 확인하기)
attributes: Getting and setting attributes (속성을 설정하고 확인하기)
attributes: Getting and setting attributes (속성을 설정하고 확인하기)
avas: Some non-standard models
axis: Low-level plotting commands

B
boxplot: 일표본과 이표본 검정
break: Repetitive execution
bruto: Some non-standard models

C
c: 벡터와 할당
c: 문자형 벡터
c: 배열에 사용되는 결합함수 c()
c: Concatenating lists (리스트 연결하기)
C: Contrasts
cbind: Forming partitioned matrices
coef: Generic functions for extracting model information
coefficients: Generic functions for extracting model information
contour: Display graphics
contrasts: Contrasts
coplot: Displaying multivariate data
cos: 벡터 연산
crossprod: Index matrices (인덱스 행렬)
crossprod: Multiplication
cut: 요인을 이용하여 도수분포표 생성하기

D
data: 내장된 데이터셋을 이용하기
data.frame: 데이터 프레임 생성하기
density: 데이터의 분포 살펴보기
det: 특이값 분해 및 행렬식
detach: attach()와 detach()
determinant: 특이값 분해 및 행렬식
dev.list: 다수의 그래픽 디바이스 (graphic devices)
dev.next: 다수의 그래픽 디바이스 (graphic devices)
dev.off: 다수의 그래픽 디바이스 (graphic devices)
dev.prev: 다수의 그래픽 디바이스 (graphic devices)
dev.set: 다수의 그래픽 디바이스 (graphic devices)
deviance: Generic functions for extracting model information
diag: Multiplication
dim: 배열
dotchart: Display graphics
drop1: Updating fitted models

E
ecdf: 데이터의 분포 살펴보기
edit: 데이터를 편집하기
eigen: 고유값과 고유벡터
else: Conditional execution
Error: Analysis of variance and model comparison
example: 도움말 기능 사용하기
exp: 벡터 연산

F
F: 논리형 벡터
factor: Factors (요인)
FALSE: 논리형 벡터
fivenum: 데이터의 분포 살펴보기
for: Repetitive execution
formula: Generic functions for extracting model information
function: Writing your own functions (사용자 정의함수 작성하기)

G
getAnywhere: Object orientation (객체지향적 방법)
getS3method: Object orientation (객체지향적 방법)
glm: The glm() function

H
help: 도움말 기능 사용하기
help: 도움말 기능 사용하기
help.search: 도움말 기능 사용하기
help.start: 도움말 기능 사용하기
hist: 데이터의 분포 살펴보기
hist: Display graphics

I
identify: Interacting with graphics
if: Conditional execution
if: Conditional execution
ifelse: Conditional execution
image: Display graphics
is.na: 결측값
is.nan: 결측값

J
jpeg: Device drivers

K
ks.test: 데이터의 분포 살펴보기

L
legend: Low-level plotting commands
length: 벡터 연산
length: The intrinsic attributes mode and length
levels: Factors (요인)
lines: Low-level plotting commands
list: Lists (리스트)
lm: Linear models
lme: Some non-standard models
locator: Interacting with graphics
loess: Some non-standard models
loess: Some non-standard models
log: 벡터 연산
lqs: Some non-standard models
lsfit: 최소제곱법과 QR 분해법

M
mars: Some non-standard models
max: 벡터 연산
mean: 벡터 연산
methods: Object orientation (객체지향적 방법)
min: 벡터 연산
mode: The intrinsic attributes mode and length

N
NA: 결측값
NaN: 결측값
ncol: 행렬의 기능들
next: Repetitive execution
nlm: Nonlinear least squares and maximum likelihood models
nlm: Least squares
nlm: Maximum likelihood
nlme: Some non-standard models
nlminb: Nonlinear least squares and maximum likelihood models
nrow: 행렬의 기능들

O
optim: Nonlinear least squares and maximum likelihood models
order: 벡터 연산
ordered: 순서형 요인
ordered: 순서형 요인
outer: 두 배열의 외적

P
pairs: Displaying multivariate data
par: The par() function
paste: 문자형 벡터
pdf: Device drivers
persp: Display graphics
plot: Generic functions for extracting model information
plot: The plot() function
pmax: 벡터 연산
pmin: 벡터 연산
png: Device drivers
points: Low-level plotting commands
polygon: Low-level plotting commands
postscript: Device drivers
predict: Generic functions for extracting model information
print: Generic functions for extracting model information
prod: 벡터 연산

Q
qqline: 데이터의 분포 살펴보기
qqline: Display graphics
qqnorm: 데이터의 분포 살펴보기
qqnorm: Display graphics
qqplot: Display graphics
qr: 최소제곱법과 QR 분해법
quartz: Device drivers

R
range는 주어진 벡터 x의 모든 구성요소 중 최소값과 최대값을 c(min(x), max(x))의 형태로 출력하며, 이름 그대로 벡터 변수의 범위를 구할 때 사용 합니다.: 벡터 연산
rbind: Forming partitioned matrices
read.table: The read.table() function
rep: Generating regular sequences (규칙성을 지닌 일련의 숫자들을 생성하기)
repeat: Repetitive execution
resid: Generic functions for extracting model information
residuals: Generic functions for extracting model information
rlm: Some non-standard models
rm: 영구적 데이터 생성 및 객체의 제거

S
scan: The scan() function
sd: The function tapply() and ragged arrays
search: 탐색경로를 관리하기
seq: Generating regular sequences (규칙성을 지닌 일련의 숫자들을 생성하기)
shapiro.test: 데이터의 분포 살펴보기
sin: 벡터 연산
sink: 파일에 작성된 명령어를 실행하거나 출력방향을 파일로 변경하기
solve: 선형방정식과 역행렬
sort: 벡터 연산
source: 파일에 작성된 명령어를 실행하거나 출력방향을 파일로 변경하기
split: Repetitive execution
sqrt: 벡터 연산
stem: 데이터의 분포 살펴보기
step: Generic functions for extracting model information
step: Updating fitted models
sum: 벡터 연산
summary: 데이터의 분포 살펴보기
summary: Generic functions for extracting model information
svd: 특이값 분해 및 행렬식

T
T: 논리형 벡터
t: 배열의 전치에 사용되는 일반화된 방법
t.test: 일표본과 이표본 검정
table: Index matrices (인덱스 행렬)
table: 요인을 이용하여 도수분포표 생성하기
tan: 벡터 연산
tapply: The function tapply() and ragged arrays
text: Low-level plotting commands
title: Low-level plotting commands
tree: Some non-standard models
TRUE: 논리형 벡터

U
unclass: 객체의 클래스
update: Updating fitted models

V
var: 벡터 연산
var: The function tapply() and ragged arrays
var.test: 일표본과 이표본 검정
vcov: Generic functions for extracting model information
vector: 벡터와 할당

W
while: Repetitive execution
wilcox.test: 일표본과 이표본 검정
windows: Device drivers

X
X11: Device drivers

Jump to:   !   %   &   *   +   -   .   /   :   <   =   >   ?   ^   |   ~  
A   B   C   D   E   F   G   H   I   J   K   L   M   N   O   P   Q   R   S   T   U   V   W   X  

Appendix E 개념과 관련된 색인

Jump to:   A   B   C   D   E   F   G   I   K   L   M   N   O   P   Q   R   S   T   U   V   W          
Index Entry  Section

A
Additive models: Some non-standard models
Analysis of variance: Analysis of variance and model comparison
Arithmetic functions and operators: 벡터 연산
Assignment: 벡터와 할당
Attributes: Objects

B
Binary operators: 새로운 이항연산자를 정의하기
Box plots: 일표본과 이표본 검정

C
Classes: 객체의 클래스
Classes: Object orientation (객체지향적 방법)
Concatenating lists (리스트 연결하기): Concatenating lists (리스트 연결하기)
Contrasts: Contrasts
CRAN: 사용자-기여 패키지(Contributed packages)와 CRAN

D
Data frames (데이터 프레임): Data frames (데이터 프레임)
Default values: 인자명과 기본값
Density estimation: 데이터의 분포 살펴보기
Determinants: 특이값 분해 및 행렬식
Dynamic graphics: Dynamic graphics

E
Empirical CDFs: 데이터의 분포 살펴보기

F
Factors (요인): Factors (요인)
Factors (요인): Contrasts
Families: Families
Formulae: 식(formulae)을 통한 통계모형의 정의

G
Generalized linear models: Generalized linear models
Generic functions: Object orientation (객체지향적 방법)
Graphics parameters: The par() function

I
Indexing of and by arrays: Array indexing
Indexing vectors: 인덱스 벡터

K
Kolmogorov-Smirnov test: 데이터의 분포 살펴보기

L
Least squares fitting: 최소제곱법과 QR 분해법
Linear equations: 선형방정식과 역행렬
Linear models: Linear models
Lists (리스트): Lists (리스트)
Local approximating regressions: Some non-standard models
Loops and conditional execution (반복 및 조건부 실행): Loops and conditional execution (반복 및 조건부 실행)

M
Matrices: 배열
Maximum likelihood: Maximum likelihood
Mixed models: Some non-standard models

N
Named arguments: 인자명과 기본값
Nonlinear least squares: Nonlinear least squares and maximum likelihood models

O
Object orientation (객체지향적 방법): Object orientation (객체지향적 방법)
Objects: Objects

P
Packages (패키지): R과 통계
Packages (패키지): Packages (패키지)

Q
QR decomposition: 최소제곱법과 QR 분해법
Quantile-quantile plots: 데이터의 분포 살펴보기

R
Reading data from files (파일로부터 데이터 읽어오기): Reading data from files (파일로부터 데이터 읽어오기)
Recycling rule: 벡터 연산
Recycling rule: The recycling rule
Regular sequences: Generating regular sequences (규칙성을 지닌 일련의 숫자들을 생성하기)
Removing objects: 영구적 데이터 생성 및 객체의 제거
Robust regression: Some non-standard models

S
Scope (스코프): Scope (스코프)
Search path: 탐색경로를 관리하기
Shapiro-Wilk test: 데이터의 분포 살펴보기
Singular value decomposition: 특이값 분해 및 행렬식
Statistical models: Statistical models in R (R에서 사용되는 통계모형들)
Student’s t test: 일표본과 이표본 검정

T
Tabulation: 요인을 이용하여 도수분포표 생성하기
Tree-based models: Some non-standard models

U
Updating fitted models: Updating fitted models

V
Vectors: Simple manipulations numbers and vectors

W
Wilcoxon test: 일표본과 이표본 검정
Workspace: 영구적 데이터 생성 및 객체의 제거
Writing functions: Writing your own functions (사용자 정의함수 작성하기)

결측값: 결측값
고유값과 고유벡터: 고유값과 고유벡터
그래픽 디바이스 드라이버 (graphic device driver): Device drivers
그룹화된 표현: 그룹화된 표현

내장된 데이터셋을 이용하기: 내장된 데이터셋을 이용하기
네임스페이스 (Namespaces): 네임스페이스 (Namespaces)
문자형 벡터: 문자형 벡터
배열: 배열
배열의 외적(outer products): 두 배열의 외적
배열의 전치에 사용되는 일반화된 방법: 배열의 전치에 사용되는 일반화된 방법

순서형 요인: Factors (요인)
순서형 요인: Contrasts
외부파일에 저장된 명령 실행 및 외부파일로 결과 저장하기: 파일에 작성된 명령어를 실행하거나 출력방향을 파일로 변경하기
일표본과 이표본 검정: 일표본과 이표본 검정
제어문: 제어문

행렬의 곱셈: Multiplication
확률분포함수: 확률분포함수
환경 설정하기: 환경 설정하기

Jump to:   A   B   C   D   E   F   G   I   K   L   M   N   O   P   Q   R   S   T   U   V   W          

Appendix F References (참고문헌)

D. M. Bates and D. G. Watts (1988), Nonlinear Regression Analysis and Its Applications. John Wiley & Sons, New York.

Richard A. Becker, John M. Chambers and Allan R. Wilks (1988), The New S Language. Chapman & Hall, New York. This book is often called the “Blue Book”.

John M. Chambers and Trevor J. Hastie eds. (1992), Statistical Models in S. Chapman & Hall, New York. This is also called the “White Book”.

John M. Chambers (1998) Programming with Data. Springer, New York. This is also called the “Green Book”.

A. C. Davison and D. V. Hinkley (1997), Bootstrap Methods and Their Applications, Cambridge University Press.

Annette J. Dobson (1990), An Introduction to Generalized Linear Models, Chapman and Hall, London.

Peter McCullagh and John A. Nelder (1989), Generalized Linear Models. Second edition, Chapman and Hall, London.

John A. Rice (1995), Mathematical Statistics and Data Analysis. Second edition. Duxbury Press, Belmont, CA.

S. D. Silvey (1970), Statistical Inference. Penguin, London.


Footnotes

(1)

ACM Software Systems award, 1998: https://awards.acm.org/award_winners/chambers_6640862.cfm.

(2)

R 패키지들에서 사용되는 R 코드의 경우를 포함하여 오로지 A–Za–z0–9만이 사용되어야 합니다.

(3)

문자열 내부 또는 함수의 정의에서 사용되는 인자들을 나열하는 부분은 제외

(4)

일부 콘솔의 경우 더 이상 입력할 수 없도록 하거나, 경고메시지 없이 입력범위를 초과한 부분을 잘라내기도 합니다. 어떤 콘솔의 경우에는 초과된 부분을 다음행의 새로운 시작으로 사용하기도 합니다.

(5)

여기에서 사용된 것과 같이 “dot”으로 시작하는 이름을 가진 파일은 UNIX 환경에서 파일들의 목록을 출력시에 보여지지 않게(invisible) 됩니다. and in default GUI file listings on OS X and Windows.

(6)

list 처럼 벡터형의 인자가 아닌 데이터에 대해 c() 함수를 사용하면, 그 결과가 다소 다르게 나타납니다. 자세한 것은 See Concatenating lists (리스트 연결하기).

(7)

실제로 이 표현식 실행 후, 아직 다음 명령문을 실행하지 않았다면 .Last.value 함수를 사용하여 결과물을 한 번 더 확인하는 것은 가능합니다.

(8)

paste(...,collapse=ss)라고 하게되면 인자들 사이에 ss를 넣어 하나의 문자열을 만듭니다. 문자열을 다루는 방법에 대해 더 많이 알고 싶으시다면 subsubstring를 살펴보시길 바랍니다.

(9)

numeric(수치형) 모드라는 것은 사실 integer(정수형)과 double precision (배정밀도)라는 두가지의 다른 모드가 합쳐진 것입니다

(10)

그러나, length(object)가 항상 본질적이고 유용한 정보를 제공하는 것은 아닙니다. object가 함수인 경우가 여기에 해당합니다.

(11)

일반적으로, 숫자에서 문자로 강제형변환 한 뒤 다시 숫자로 변경할때에는, 문자형을 표현할 때의 round off errors(반올림 오차) 때문에, 원래의 숫자와 완전히 같은 값이 되지는 않습니다.

(12)

‘formal’ 또는 ‘S4’ 와 같은 다른 종류의 클래스에 기반한 스타일은 패키지 methods를 통해 사용 가능합니다.

(13)

tapply(incomes, state)’의 경우와 같이 tapply()의 두번째 인자가 꼭 요인(factor)일 필요는 없습니다. 이 함수는 필요한 경우에는 as.factor()를 사용한 것처럼 두번째 인자를 강제형변환 coerced 한 후, 연산을 수행하기 때문입니다.

(14)

x %*% x는 올바른 식이라고 보기 어려운데, 이는 사용자가 수행하고자 하는 연산이 x’x 인지 x x’인지 분명하지 않기 때문입니다. 여기에서 x는 열벡터 입니다.이 경우, 더 작은 크기의 행렬을 선호하는 특성 때문에 스칼라 값(즉, 한개의 숫자)인 x’x을 결과로 출력합니다.x x’의 행렬연산을 수행하고 싶다면 cbind(x) %*% x 또는 x %*% rbind(x)을 사용해야 하는데, rbind() 이나 cbind()을 사용한 결과가 항상 행렬이기 때문입니다.하지만, 아무래도 x’x이나 x x’을 계산하는 가장 좋은 방법은 각각의 경우 함수 crossprod(x)x %o% x를 사용하는 것입니다.

(15)

좀 더 좋은 방법은 행렬의 제곱근(matrix square root)인 B를 찾는 것입니다. 여기서 행렬의 제곱근 B는 A = BB’으로 정의되며, A의 콜레스키 분해(Cholesky decomposition)나 아이겐 분해(eigen decomposition)를 이용하면 By = x의 해의 제곱길이 (squared length)를 찾는 과정을 통해 이차 행렬식을 풀게 됩니다.

(16)

문자형 벡터의 경우, data.frame()함수의 stringsAsFactors 인자를 사용하여 요인으로 강제변환하는 것도 가능합니다

(17)

두번째로 출력된 autoload에 대해서는 온라인 도움말을 살펴보시길 바랍니다

(18)

유닉스 운영체제에서 Sed 또는 Awk와 같은 유틸리티들

(19)

또는 lattice에 있는 xyplot함수를 이용할 수 있습니다.

(20)

Statistical models in R (R에서 사용되는 통계모형들)에 설명된 다른 방법들을 살펴보시길 바랍니다

(21)

어떤한 의미로는 이것은 S-PLUS의 기능을 흉내낸 것처럼 보일 수도 있습니다. 그 이유는 S-PLUS의 연산이 항상 전역변수를 생성하고 이에 값을 할당하기 때문입니다

(22)

UNIX에서는 숨겨진 파일입니다.

(23)

마찬가지로, ANCOVA를 표기할 때도 classification을 따로 명시하지는 않지만, 이 방법의 역시 보통 연속형 변수인 공변량(covariate)이 포함된다는 것 외에는 ANOVA와 유사한 분석을 수행하므로 이렇게 표현한 것 같습니다.

(24)

물론 이 중 일부 그래픽 파라미터들은 현재 디바이스의 크기 처럼, 오직 정보 확인의 목적만을 가진 것들도 있습니다.

(25)

프로세스당 3Gb를 지원하는 Windows에서는 2.5Gb이며, 이는 rw-FAQ Q2.9를 살펴보세요; 일부 64 비트의 Windows는 3.5Gb입니다

(26)

R 2.13.0부터

(27)

‘Emacs Speaks Statistics’패키지를 말하며, URL http://ESS.R-project.org를 살펴보시길 바랍니다

(28)

PC 키보드에서는 이것은 일반적으로 Alt 키이거나 가끔 ‘Windows’키이기도 합니다. Mac 키보드에서는 일반적으로 사용가능한 메타키가 없습니다