การทำงานกับพจนานุกรม / รายการใน R


93

ฉันมีคำถามเล็กน้อย: ฉันไม่พบโครงสร้างข้อมูลพจนานุกรมใน R ดังนั้นฉันจึงใช้ list แทน (เช่น "word" -> number) ดังนั้นตอนนี้ฉันมีปัญหาในการรับรายการคีย์ มีใครรู้บ้าง?

คำตอบ:


121

ใช่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
+1 สำหรับการตอบคำถามโดยไม่มีคำเกี่ยวกับแนวทางที่ไม่มีประสิทธิผลของ OP
Marek

3
ขึ้นอยู่กับวัตถุประสงค์ในการใช้รายการเป็นพร็อกซีสำหรับพจนานุกรมคุณอาจต้องพึงระลึกไว้เสมอว่าการค้นหา "คีย์" สำหรับรายการคือ O (n) มากกว่า O (1) ซึ่งเป็นสิ่งที่คุณคาดหวัง พจนานุกรม (ซึ่งแฮชคีย์)
เอกา

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:

ก) วิธีการคืนค่าทั้งหมดของพจนานุกรม:

>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) จะปฏิบัติตามข้อกำหนดของพจนานุกรมจริงได้อย่างไร - คีย์นั้นไม่สามารถทำซ้ำได้ (คีย์ที่ไม่ซ้ำกัน)? คุณต้องรวม b) และ c) และสร้างฟังก์ชันที่ตรวจสอบว่ามีคีย์ดังกล่าวหรือไม่และทำในสิ่งที่คุณต้องการเช่นไม่อนุญาตให้แทรกค่าอัปเดตหากใหม่แตกต่างจากคีย์เก่าหรือสร้างคีย์ใหม่ (เช่น เพิ่มจำนวนเพื่อให้ไม่ซ้ำกัน)

จ) วิธีลบคู่ตามคีย์จากพจนานุกรม:

ฟู <-foo [ซึ่ง (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 วินาที! ฉันเข้าใจแฮชได้ดี แต่ใคร ๆ ก็สามารถยืนยันได้เมื่อค้นหาชื่อในรายการว่าใช้การค้นหาประเภทใด นี่เป็นเพียงการวนซ้ำรายการภายใต้ชื่อที่ตรงกันหรือไม่? ฉันอยากจะเข้าใจว่าทำไมรายการจึงช้ามากและทำไมแฮชจึงเร็วมากสำหรับคีย์จำนวนมาก
ฟิลิป

@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"

คุณจะเพิ่มหลายค่าได้อย่างไร? ฉันได้ลองทำซ้ำคีย์แล้ว แต่จะเก็บเฉพาะค่าสุดท้ายเท่านั้น ฉันได้ลองกำหนดรายการแล้ว แต่ไม่ได้ผล
กัน

พจนานุกรมไม่เคยเก็บหลายค่าต่อคีย์ คุณสามารถกำหนดรายการให้กับคีย์ได้หากต้องการ
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.