간단한 배경 : 널리 사용되는 많은 (대부분의) 현대 프로그래밍 언어에는 적어도 몇 개의 ADT (추상 데이터 유형)가 공통적으로 있습니다.
-
문자열 (문자로 구성된 시퀀스)
-
목록 (정렬 된 값 모음) 및
-
지도 기반 유형 (키를 값에 매핑하는 정렬되지 않은 배열)
R 프로그래밍 언어에서 처음 두 개는 각각 character
및 로 구현됩니다 vector
.
R을 배우기 시작했을 때, 거의 처음부터 두 가지가 명백 list
했습니다 .R에서 가장 중요한 데이터 유형입니다 (R의 부모 클래스이기 때문에 data.frame
). 그리고 두 번째로, 그들이 어떻게 작동했는지 이해할 수 없었습니다. 내 코드에서 올바르게 사용하기에 충분하지 않습니다.
우선 R의 list
데이터 유형은 맵 ADT ( dictionary
Python, NSMutableDictionary
Objective C, hash
Perl 및 Ruby, object literal
Javascript 등)를 간단하게 구현 한 것 같습니다 .
예를 들어, 키-값 쌍을 생성자 (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 과 매핑 유형의 세 가지 중요한 차이점 :
먼저 , list
R에서 S는이다 정렬 막 벡터처럼 그 값을 키가되는 경우에도 (즉, 키는 임의의 해쉬 값이 아닌 정수 순차적 일 수있다), 수집. 거의 항상 다른 언어의 매핑 데이터 형식이 정렬되지 않았습니다 .
둘째 , list
S는 당신이 전달되지 않습니다에도 불구하고 기능에서 반환 할 수 있습니다 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로 시작하는 순차 정수입니까? (그렇지 않으면 우리는 이러한 유형의 강요 할 수없는 것, 내가 생각,하지만 난 대답은 ‘예’확신에서 멀리이다list
w /로 전화 벡터에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 list
와 vector
R 의 차이점을 실제로 지적하기 때문에 질문의 마지막 부분을 해결하십시오 .
이 두 표현식이 같은 결과를 반환하지 않는 이유는 무엇입니까?
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 인 벡터입니다. 반면에 목록의 첫 번째 요소를 반환합니다.x
x
x[[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)