[r] R에서 목록을 올바르게 사용하는 방법?

간단한 배경 : 널리 사용되는 많은 (대부분의) 현대 프로그래밍 언어에는 적어도 몇 개의 ADT (추상 데이터 유형)가 공통적으로 있습니다.

  • 문자열 (문자로 구성된 시퀀스)

  • 목록 (정렬 된 값 모음) 및

  • 지도 기반 유형 (키를 값에 매핑하는 정렬되지 않은 배열)

R 프로그래밍 언어에서 처음 두 개는 각각 character및 로 구현됩니다 vector.

R을 배우기 시작했을 때, 거의 처음부터 두 가지가 명백 list했습니다 .R에서 가장 중요한 데이터 유형입니다 (R의 부모 클래스이기 때문에 data.frame). 그리고 두 번째로, 그들이 어떻게 작동했는지 이해할 수 없었습니다. 내 코드에서 올바르게 사용하기에 충분하지 않습니다.

우선 R의 list데이터 유형은 맵 ADT ( dictionaryPython, NSMutableDictionaryObjective C, hashPerl 및 Ruby, object literalJavascript 등)를 간단하게 구현 한 것 같습니다 .

예를 들어, 키-값 쌍을 생성자 (Python의 경우는 dict아님 list) 에 전달하여 Python 사전과 같이 생성합니다 .

x = list("ev1"=10, "ev2"=15, "rv"="Group 1")

그리고 파이썬 사전과 같이 R List의 항목에 액세스합니다 (예 🙂 x['ev1']. 마찬가지로 다음과 같이 ‘키’ 또는 ‘값’ 만 검색 할 수 있습니다 .

names(x)    # fetch just the 'keys' of an R list
# [1] "ev1" "ev2" "rv"

unlist(x)   # fetch just the 'values' of an R list
#   ev1       ev2        rv 
#  "10"      "15" "Group 1" 

x = list("a"=6, "b"=9, "c"=3)

sum(unlist(x))
# [1] 18

그러나 R list은 다른지도 유형의 ADT 와 다릅니다 (어쨌든 내가 배운 언어 중에서). 내 생각에 이것은 S의 초기 사양, 즉 기초부터 데이터 / 통계 DSL (도메인 특정 언어)을 설계하려는 의도의 결과라고 생각합니다.

list널리 사용되는 다른 언어 (예 : Python, Perl, JavaScript)에서 R 과 매핑 유형의 세 가지 중요한 차이점 :

먼저 , listR에서 S는이다 정렬 막 벡터처럼 그 값을 키가되는 경우에도 (즉, 키는 임의의 해쉬 값이 아닌 정수 순차적 일 수있다), 수집. 거의 항상 다른 언어의 매핑 데이터 형식이 정렬되지 않았습니다 .

둘째 , listS는 당신이 전달되지 않습니다에도 불구하고 기능에서 반환 할 수 있습니다 list당신이 함수를 호출 할 때, 그리고 비록 (가) 반환 된 기능 list(명시 적)이 포함되어 있지 않습니다 list물론 (생성자, 당신에 의해 실제로이 처리 할 수 을 호출하여 반환 된 결과를 래핑 unlist:

x = strsplit(LETTERS[1:10], "")     # passing in an object of type 'character'

class(x)                            # returns 'list', not a vector of length 2
# [1] list

세 번째 R의의 독특한 기능 list들 : 그들이 다른 ADT의 구성원이 될 수 있다는 것을하지 않는 것, 당신이 그렇게하려고하면 다음 기본 컨테이너는 강제 변환됩니다 list. 예 :

x = c(0.5, 0.8, 0.23, list(0.5, 0.2, 0.9), recursive=TRUE)

class(x)
# [1] list

여기에서의 나의 의도는 언어를 비판하거나 언어를 문서화하는 방법이 아니다. 마찬가지로 list데이터 구조 또는 작동 방식에 문제가 있음을 제안하지 않습니다 . 내가 추구하는 것은 그것들이 어떻게 작동하는지에 대한 나의 이해로 코드에서 올바르게 사용할 수 있습니다.

내가 더 잘 이해하고 싶은 종류는 다음과 같습니다.

  • 함수 호출이 언제 list(예 : strsplit위에서 언급 한 표현)을 반환 할 것인지를 결정하는 규칙은 무엇입니까 ?

  • 명시 적으로 이름을 list(예 :)에 할당하지 않으면 list(10,20,30,40)기본 이름은 1로 시작하는 순차 정수입니까? (그렇지 않으면 우리는 이러한 유형의 강요 할 수없는 것, 내가 생각,하지만 난 대답은 ‘예’확신에서 멀리이다 listw /로 전화 벡터에 unlist.)

  • 이 두 개의 다른 연산자 인 [], 및 왜 같은 결과를 [[]]반환 합니까?

    x = list(1, 2, 3, 4)

    두 표현식 모두 “1”을 반환합니다.

    x[1]

    x[[1]]

  • 왜이 두 표현식 이 같은 결과를 반환 하지 않습니까?

    x = list(1, 2, 3, 4)

    x2 = list(1:4)

R 문서 ( ?list, R-intro) 를 가리 키지 마십시오. 필자는이 내용을주의 깊게 읽었으며 위에서 언급 한 유형의 질문에 대답하는 데 도움이되지 않습니다.

(마지막으로, 최근 에 S4 클래스를 통해 일반적인 맵 유형 동작 hash을 구현 하는 R 패키지 (CRAN에서 사용 가능)를 배우고 사용하기 시작했습니다 .이 패키지를 확실히 추천 할 수 있습니다.)



답변

a listvectorR 의 차이점을 실제로 지적하기 때문에 질문의 마지막 부분을 해결하십시오 .

이 두 표현식이 같은 결과를 반환하지 않는 이유는 무엇입니까?

x =리스트 (1, 2, 3, 4); x2 = 목록 (1 : 4)

목록은 각 요소로서 다른 클래스를 포함 할 수 있습니다. 따라서 첫 번째 요소는 문자형 벡터이고 두 번째 요소는 데이터 프레임 등의 목록을 가질 수 있습니다.이 경우 두 개의 다른 목록을 만들었습니다. x길이 x2가 각각 4 개인 벡터가 있고 길이가 4 인 벡터 가 1 개인 경우

> length(x[[1]])
[1] 1
> length(x2[[1]])
[1] 4

이것들은 완전히 다른 목록입니다.

R리스트는 해시 맵 과 매우 비슷 합니다 각 인덱스 값이 어떤 객체와도 연관 될 수 있다는 점에서 데이터 구조 합니다. 다음은 3 가지 다른 클래스 (함수 포함)를 포함하는 간단한 예입니다.

> complicated.list <- list("a"=1:4, "b"=1:3, "c"=matrix(1:4, nrow=2), "d"=search)
> lapply(complicated.list, class)
$a
[1] "integer"
$b
[1] "integer"
$c
[1] "matrix"
$d
[1] "function"

마지막 요소가 검색 함수라고 가정하면 다음과 같이 호출 할 수 있습니다.

> complicated.list[["d"]]()
[1] ".GlobalEnv" ...

이것에 대한 최종 의견으로 : data.frame 는 실제로 ( data.frame문서에서) 목록입니다 .

데이터 프레임은 ”data.frame ”클래스에서 고유 한 행 이름을 가진 동일한 수의 행에 대한 변수 목록입니다.

그렇기 때문에의 열 data.frame은 다른 데이터 유형을 가질 수 있지만 행렬의 열은 그렇지 않습니다. 예를 들어, 숫자와 문자가 포함 된 행렬을 만들려고합니다.

> a <- 1:4
> class(a)
[1] "integer"
> b <- c("a","b","c","d")
> d <- cbind(a, b)
> d
 a   b
[1,] "1" "a"
[2,] "2" "b"
[3,] "3" "c"
[4,] "4" "d"
> class(d[,1])
[1] "character"

두 번째 열에 문자가 있기 때문에 첫 번째 열의 데이터 유형을 숫자로 변경하는 방법에 유의하십시오.

> d[,1] <- as.numeric(d[,1])
> class(d[,1])
[1] "character"


답변

질문에 대해서는 순서대로 처리하고 몇 가지 예를 들어 보겠습니다.

1 ) return 문이 추가되면 목록이 반환됩니다. 치다

 R> retList <- function() return(list(1,2,3,4)); class(retList())
 [1] "list"
 R> notList <- function() return(c(1,2,3,4)); class(notList())
 [1] "numeric"
 R> 

2 ) 이름은 단순히 설정되지 않습니다 :

R> retList <- function() return(list(1,2,3,4)); names(retList())
NULL
R> 

3 ) 그들은 같은 일을 반환하지 않습니다. 당신의 예는

R> x <- list(1,2,3,4)
R> x[1]
[[1]]
[1] 1
R> x[[1]]
[1] 1

여기서 – x[1]의 첫 번째 요소를 반환합니다 . 모든 스칼라는 길이가 1 인 벡터입니다. 반면에 목록의 첫 번째 요소를 반환합니다.xxx[[1]]

4 ) 마지막으로 두 요소는 각각 4 개의 스칼라가 포함 된 목록과 단일 요소가있는 목록 (4 개의 요소로 구성된 벡터)에서 서로 다릅니다.


답변

질문의 일부를 가져 오려면 :

이 기사 색인에이 차이의 문제 해결 [][[]] .

간단히 [[]]는 목록에서 단일 항목을 []선택하고 선택한 항목의 목록을 반환합니다. 예제에서 x = list(1, 2, 3, 4)'항목 1은 단일 정수이지만 x[[1]]단일 1을 x[1]반환하고 값이 하나만있는 목록을 반환합니다.

> x = list(1, 2, 3, 4)
> x[1]
[[1]]
[1] 1

> x[[1]]
[1] 1


답변

목록이 작동하는 순서대로 작동하는 한 가지 이유는 모든 노드에서 유형을 포함 할 수있는 벡터가 아닌 정렬 된 컨테이너의 필요성을 해결하기위한 것입니다. 목록은 R의 기본 구성을 포함하여 R의 다양한 목적으로 재사용됩니다.data.frame 임의의 유형 (그러나 동일한 길이)의 벡터리스트 인 .

이 두 표현식이 같은 결과를 반환하지 않는 이유는 무엇입니까?

x = list(1, 2, 3, 4); x2 = list(1:4)

@Shane의 답변에 추가하려면 동일한 결과를 얻으려면 다음을 시도하십시오.

x3 = as.list(1:4)

벡터 1:4를 목록으로 강제합니다 .


답변

이것에 하나 이상의 포인트를 추가하십시오.

R은에서 파이썬 딕셔너리에 해당하는 데이터 구조 가지고 패키지를 . 이 블로그 게시물에서 Open Data Group의 내용을 읽을 수 있습니다 . 다음은 간단한 예입니다.hash

> library(hash)
> h <- hash( keys=c('foo','bar','baz'), values=1:3 )
> h[c('foo','bar')]
<hash> containing 2 key-value pairs.
  bar : 2
  foo : 1

유용성 측면에서 hash클래스는 목록과 매우 유사합니다. 그러나 대규모 데이터 세트의 경우 성능이 더 좋습니다.


답변

당신은 말합니다 :

다른 경우, 함수를 호출 할 때 List에 전달한 적이없고 함수에 List 생성자가 포함되어 있지 않더라도 함수에서 목록을 반환 할 수 있습니다.

x = strsplit(LETTERS[1:10], "") # passing in an object of type 'character'
class(x)
# => 'list'

그리고 이것이 문제라고 제안한다고 생각합니다 (?). 나는 그것이 왜 문제가 아닌지 당신에게 이야기하기 위해 왔습니다 :-). 문자열 분리를 할 때 1 요소 길이의 요소가있는 목록 x[[1]]이 있으므로와 동일한 것을 알 수 있습니다 unlist(x)[1]. 그러나 strsplit각 빈에서 길이가 다른 결과가 반환 되면 어떻게 될까요? 단순히 벡터 (목록과 목록)를 반환하는 것은 전혀 효과가 없습니다.

예를 들어 :

stuff <- c("You, me, and dupree",  "You me, and dupree",
           "He ran away, but not very far, and not very fast")
x <- strsplit(stuff, ",")
xx <- unlist(strsplit(stuff, ","))

첫 번째 경우 ( x:는 목록을 반환) 세 번째 문자열의 두 번째 “부분”이 무엇인지 알 수 있습니다. 예를 들면 다음과 같습니다.x[[3]][2] . xx결과가 “비공개”( unlist-ed) 되었으므로 어떻게 똑같이 할 수 있습니까?


답변

x = list(1, 2, 3, 4)
x2 = list(1:4)
all.equal(x,x2)

1 : 4는 c (1,2,3,4)와 동일하므로 동일하지 않습니다. 당신이 그들을 동일하게하고 싶다면 :

x = list(c(1,2,3,4))
x2 = list(1:4)
all.equal(x,x2)