R에서 사전 / 목록 작업


93

사소한 질문이 있습니다. R에서 사전 데이터 구조를 찾을 수 없어서 대신 목록을 사용했습니다 ( "word"-> number). 그래서 지금은 키 목록을 얻는 방법에 문제가 있습니다. 아는 사람 있나요?

답변:


120

예, list유형은 좋은 근사치입니다. names()목록에서 사용 하여 '키'를 설정하고 검색 할 수 있습니다 .

> foo <- vector(mode="list", length=3)
> names(foo) <- c("tic", "tac", "toe")
> foo[[1]] <- 12; foo[[2]] <- 22; foo[[3]] <- 33
> foo
$tic
[1] 12

$tac
[1] 22

$toe
[1] 33

> names(foo)
[1] "tic" "tac" "toe"
> 

18
OP의 비효율적 인 접근 방식에 대해 한마디없이 질문에 답하는 경우 +1.
Marek

3
사전에 대한 프록시로 목록의 용도에 따라 목록에 대한 "키"조회는 O (1)이 아닌 O (n)이라는 점을 기억하는 것이 좋습니다. 사전 (해시 키)
egnha

4
예, environment유형은 R에서 사용되지만 덜 일반적이거나 덜 알려져 있습니다.
Dirk Eddelbuettel

58

"숫자"값이 모두 동일한 모드이면 목록이 필요하지 않습니다. Dirk Eddelbuettel의 예를 들어 보면 :

> foo <- c(12, 22, 33)
> names(foo) <- c("tic", "tac", "toe")
> foo
tic tac toe
 12  22  33
> names(foo)
[1] "tic" "tac" "toe"

목록은 값이 혼합 모드 (예 : 문자 및 숫자) 또는 벡터 인 경우에만 필요합니다.

목록과 벡터 모두에 대해 개별 요소를 이름으로 부분 집합화할 수 있습니다.

> foo["tac"]
tac 
 22 

또는 목록 :

> foo[["tac"]]
[1] 22

1
c(12,22,33)이 사전 스타일 R 구조 foo 의 목록 을 어떻게 얻을 수 있습니까? unlist(lapply(FUN=function(a){foo[[a]]},X = 1:length(foo)))매우 불편합니다. 이것에 대한 준비된 기능이 있습니까? 질문을 여기
hhh

18

Calimo에 대한 약간의 대답을 확장하기 위해 R에서이 유사 사전을 만드는 동안 유용 할 수있는 몇 가지 사항을 더 제시합니다.

a) 사전의 모든 값을 반환하는 방법 :

>as.numeric(foo)
[1] 12 22 33

b) 사전에 키가 포함되어 있는지 확인하십시오.

>'tic' %in% names(foo)
[1] TRUE

c) 새 키, 값 쌍을 사전에 추가하는 방법 :

c (foo, tic2 = 44)

결과 :

tic       tac       toe     tic2
12        22        33        44 

d) REAL DICTIONARY의 요구 사항을 충족하는 방법-키를 반복 할 수 없음 (고유 키)? b)와 c)를 결합하고 그러한 키가 있는지 확인하는 기능을 빌드하고 원하는 작업을 수행해야합니다. 고유하도록 번호를 추가)

e) 사전에서 키로 쌍을 삭제하는 방법 :

foo <-foo [which (foo! = foo [[ "tac"]])]


'이상한 키'와 같이 공백이 포함 된 키를 추가 할 수 있습니까?
user1700890

또한 이와 같은 것이 작동하지 않습니다 c(foo, tic2=NULL). 해결 방법이 있습니까?
user1700890

15

사전을 사용하는 이유는 성능 때문입니다. 작업에 명명 된 벡터와 목록을 사용할 수있는 것이 옳지 만 문제는 더 많은 데이터로 인해 상당히 느리고 메모리가 부족하다는 것입니다.

그러나 많은 사람들이 알지 못하는 것은 R 이 실제로 내장 된 사전 데이터 구조를 가지고 있다는 것입니다.hash = TRUE

작동 방법은 다음 예제를 참조하십시오.

# vectorize assign, get and exists for convenience
assign_hash <- Vectorize(assign, vectorize.args = c("x", "value"))
get_hash <- Vectorize(get, vectorize.args = "x")
exists_hash <- Vectorize(exists, vectorize.args = "x")

# keys and values
key<- c("tic", "tac", "toe")
value <- c(1, 22, 333)

# initialize hash
hash = new.env(hash = TRUE, parent = emptyenv(), size = 100L)
# assign values to keys
assign_hash(key, value, hash)
## tic tac toe 
##   1  22 333
# get values for keys
get_hash(c("toe", "tic"), hash)
## toe tic 
## 333   1
# alternatively:
mget(c("toe", "tic"), hash)
## $toe
## [1] 333
## 
## $tic
## [1] 1
# show all keys
ls(hash)
## [1] "tac" "tic" "toe"
# show all keys with values
get_hash(ls(hash), hash)
## tac tic toe 
##  22   1 333
# remove key-value pairs
rm(list = c("toe", "tic"), envir = hash)
get_hash(ls(hash), hash)
## tac 
##  22
# check if keys are in hash
exists_hash(c("tac", "nothere"), hash)
##     tac nothere 
##    TRUE   FALSE
# for single keys this is also possible:
# show value for single key
hash[["tac"]]
## [1] 22
# create new key-value pair
hash[["test"]] <- 1234
get_hash(ls(hash), hash)
##  tac test 
##   22 1234
# update single value
hash[["test"]] <- 54321
get_hash(ls(hash), hash)
##   tac  test 
##    22 54321

편집 :이 답변을 바탕으로 더 많은 컨텍스트가 포함 된 블로그 게시물을 작성했습니다. http://blog.ephorie.de/hash-me-if-you-can


다중 가치 관계에서 작동합니까? 예 : tic = 1 및 tic = 17
skan

@skan : 왜 그것을 시도하지 않습니까?
vonjd

이름이있는 목록을 사용하는 대신이 방법을 사용하면 실행 시간이 6 분에서 1 초로 단축되었습니다! 나는 해시를 잘 이해하지만 목록에서 이름을 찾을 때 누구든지 어떤 종류의 검색 알고리즘이 사용되는지 확인할 수 있습니까? 이름이 일치하는 목록을 반복하는 것입니까? 목록이 왜 그렇게 느린 지 정확히 이해하고 왜 많은 키에 대해 해시가 그렇게 빠른지 이해하고 싶습니다.
Phil

@vonjd R에서 사전을 사용하려고하는데이 구현을 찾았습니다. 그러나 각 값이 키 쌍과 연결되어있을 때도 작동합니까? 미리 감사드립니다.
savi

@shana : 정확히 무슨 뜻인지 예를 들어 줄 수 있습니까?
vonjd

9

이제 패키지 해시 를 사용할 수 있습니다 : https://cran.r-project.org/web/packages/hash/hash.pdf

h <- hash( keys=letters, values=1:26 )
h <- hash( letters, 1:26 )
h$a
# [1] 1
h$foo <- "bar"
h[ "foo" ]
# <hash> containing 1 key-value pair(s).
#   foo : bar
h[[ "foo" ]]
# [1] "bar"

여러 값을 어떻게 추가 할 수 있습니까? 키 반복을 시도했지만 마지막 값만 저장합니다. 나는 또한 목록 할당을 시도했지만 작동하지 않습니다
skan

사전은 키당 여러 값을 저장하지 않습니다. 원하는 경우 키에 목록을 할당 할 수 있습니다.
BallpointBen

7

Dirk의 대답의 짧은 변형 :

# Create a Color Palette Dictionary 
> color <- c('navy.blue', 'gold', 'dark.gray')
> hex <- c('#336A91', '#F3C117', '#7F7F7F')

> # Create List
> color_palette <- as.list(hex)
> # Name List Items
> names(color_palette) <- color
> 
> color_palette
$navy.blue
[1] "#336A91"

$gold
[1] "#F3C117"

$dark.gray
[1] "#7F7F7F"

4

table사전을 "위조"하려고 할 때도 많은 마일리지를 얻을 수 있다고 말씀 드리겠습니다 . 예 :

> x <- c("a","a","b","b","b","c")
> (t <- table(x))
x
a b c 
2 3 1 
> names(t)
[1] "a" "b" "c"
> o <- order(as.numeric(t))
> names(t[o])
[1] "c" "a" "b"

기타


나는 필요하다고 생각하지 않는다 as.numeric(). 테이블이 이미 숫자입니다. 다음과 같은 결과를 얻을 수 있습니다.names(t[order(t)])
Rich Scriven
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.