Rでの辞書/リストの操作


89

ささいな質問があります。Rで辞書データ構造が見つからなかったため、代わりにリストを使用しました( "word"-> numberのように)。だから、今のところ、キーのリストを取得する方法に問題があります。誰か知ってる?

回答:


118

はい、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

56

「数値」の値がすべて同じモードであれば、リストは必要ありません。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 2017

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の要件をどのように満たすか-そのキーは繰り返すことができません(UNIQUE KEYS)?b)とc)を組み合わせて、そのようなキーがあるかどうかを検証する関数を構築し、必要なことを実行する必要があります。たとえば、挿入を許可しない、新しいものが古いものと異なる場合は値を更新する、または何らかの方法でキーを再構築する(例:それにいくつかの数を追加するので、それはユニークです)

e)辞書からペアによるキーを削除する方法:

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


「奇妙なキー」など、スペースを含むキーを追加できますか?
user1700890 2017年

また、このようなものは機能しませんc(foo, tic2=NULL)。回避策はありますか?
user1700890 2017年

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で辞書を使おうとしていて、この実装を見つけました。ただし、各値がキーのペアに関連付けられている場合にも機能しますか?前もって感謝します。
サビ

@シャナ:あなたが正確に何を意味するのか例を挙げていただけますか?
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

ダークの回答の短いバリエーション:

# 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.