R中有字典功能吗

23c0lvtd  于 2023-01-06  发布在  其他
关注(0)|答案(6)|浏览(119)

有没有一种方法可以在R中创建一个“字典”,这样它就有对了?

x=dictionary(c("Hi","Why","water") , c(1,5,4))
x["Why"]=5

我问这个问题是因为我实际上在寻找一个两类变量的函数。
使得如果x=字典(c(“a”,“B”),c(5,2))

x  val
1    a  5 
2    b  2

我想计算所有x键组合的x1^2+x2

x1 x2 val1  val2  x1^2+x2
1    a  a   5     5      30
2    b  a   2     5      9
3    a  b   5     2      27
4    b  b   2     2      6

然后我希望能够使用x1和x2检索结果。获取结果[“B”,“a”] = 9
什么是做到这一点的最佳有效方法?

lymnna71

lymnna711#

我知道三个字典的R包:hashhashmapdict

***2018年7月更新:***新版本,container
***2018年9月更新:***新版本,collections

哈希

键必须是字符串。值可以是任何R对象。

library(hash)
## hash-2.2.6 provided by Decision Patterns
h <- hash() 
# set values
h[["1"]] <- 42
h[["foo"]] <- "bar"
h[["4"]] <- list(a=1, b=2)
# get values
h[["1"]]
## [1] 42
h[["4"]]
## $a
## [1] 1
## 
## $b
## [1] 2
h[c("1", "foo")]
## <hash> containing 2 key-value pair(s).
##   1 : 42
##   foo : bar
h[["key not here"]]
## NULL

要获取密钥:

keys(h)
## [1] "1"   "4"   "foo"

要获取值:

values(h)
## $`1`
## [1] 42
## 
## $`4`
## $`4`$a
## [1] 1
## 
## $`4`$b
## [1] 2
## 
## 
## $foo
## [1] "bar"

print示例:

h
## <hash> containing 3 key-value pair(s).
##   1 : 42
##   4 : 1 2
##   foo : bar

values函数接受sapply的参数:

values(h, USE.NAMES=FALSE)
## [[1]]
## [1] 42
## 
## [[2]]
## [[2]]$a
## [1] 1
## 
## [[2]]$b
## [1] 2
## 
## 
## [[3]]
## [1] "bar"
values(h, keys="4")
##   4
## a 1
## b 2
values(h, keys="4", simplify=FALSE)
## $`4`
## $`4`$a
## [1] 1
## 
## $`4`$b
## [1] 2

散列表

参见https://cran.r-project.org/web/packages/hashmap/README.html
hashmap * 不 * 提供存储任意类型对象的灵活性。
键和值被限制为"标量"对象(长度为一个字符、数字等)。值必须是相同的类型。

library(hashmap)
H <- hashmap(c("a", "b"), rnorm(2))
H[["a"]]
## [1] 0.1549271
H[[c("a","b")]]
## [1]  0.1549271 -0.1222048
H[[1]] <- 9

漂亮的print示例:

H
## ## (character) => (numeric)  
## ##         [1] => [+9.000000]
## ##         [b] => [-0.122205]
## ##         [a] => [+0.154927]

错误:

H[[2]] <- "Z"
## Error in x$`[[<-`(i, value): Not compatible with requested type: [type=character; target=double].
H[[2]] <- c(1,3)
## Warning in x$`[[<-`(i, value): length(keys) != length(values)!

命令

目前仅在Github上提供:https://github.com/mkuhn/dict

    • 优点**:* 任意 * 键和值,而且速度快。
library(dict)
d <- dict()
d[[1]] <- 42
d[[c(2, 3)]] <- "Hello!" # c(2,3) is the key
d[["foo"]] <- "bar"
d[[4]] <- list(a=1, b=2)
d[[1]]
## [1] 42
d[[c(2, 3)]]
## [1] "Hello!"
d[[4]]
## $a
## [1] 1
## 
## $b
## [1] 2

访问不存在的键会引发错误:

d[["not here"]]
## Error in d$get_or_stop(key): Key error: [1] "not here"

但是有一个很好的特性可以解决这个问题:

d$get("not here", "default value for missing key")
## [1] "default value for missing key"

获取密钥:

d$keys()
## [[1]]
## [1] 4
## 
## [[2]]
## [1] 1
## 
## [[3]]
## [1] 2 3
## 
## [[4]]
## [1] "foo"

获取值:

d$values()
## [[1]]
## [1] 42
## 
## [[2]]
## [1] "Hello!"
## 
## [[3]]
## [1] "bar"
## 
## [[4]]
## [[4]]$a
## [1] 1
## 
## [[4]]$b
## [1] 2

获取项目:

d$items()
## [[1]]
## [[1]]$key
## [1] 4
## 
## [[1]]$value
## [[1]]$value$a
## [1] 1
## 
## [[1]]$value$b
## [1] 2
## 
## 
## 
## [[2]]
## [[2]]$key
## [1] 1
## 
## [[2]]$value
## [1] 42
## 
## 
## [[3]]
## [[3]]$key
## [1] 2 3
## 
## [[3]]$value
## [1] "Hello!"
## 
## 
## [[4]]
## [[4]]$key
## [1] "foo"
## 
## [[4]]$value
## [1] "bar"

没有print示例。
这个包还提供了numvecdict函数来处理一个字典,其中数字和字符串(包括每一个的向量)可以用作键,并且只能存储数字的向量。

f4t66c6m

f4t66c6m2#

您只需使用键值对创建一个向量。

animal_sounds <- c(
  'cat' = 'meow',
  'dog' = 'woof',
  'cow' = 'moo'
)
print(animal_sounds['cat'])
# 'meow'

更新:要回答问题的第二部分,您可以创建一个 Dataframe 并按如下方式计算值:

val1 <- c(5,2,5,2) # Create val1 column
val2 <- c(5,5,2,2) # Create val2 column
df <- data.frame(val1, val2) # create dataframe variable
df['x1^2+x2'] <- val1^2 + val2 # create expression column

输出:

val1 val2 x1^2+x2
1    5    5      30
2    2    5       9
3    5    2      27
4    2    2       6
vnjpjtjt

vnjpjtjt3#

您可以只使用data.framerow.names来完成此操作:

x=data.frame(row.names=c("Hi","Why","water") , val=c(1,5,4))
x["Why",]
[1] 5
ngynwnxp

ngynwnxp4#

由于向量、矩阵、列表等在R中表现为“字典”,你可以做如下的事情:

> (x <- structure(c(5,2),names=c("a","b"))) ## "dictionary"
a b 
5 2 
> (result <- outer(x,x,function(x1,x2) x1^2+x2))
   a  b
a 30 27
b  9  6
> result["b","a"]
[1] 9

如果你想要一个你在例子中展示的表格,只要重新调整你的数组...

> library(reshape)
> (dfr <- melt(result,varnames=c("x1","x2")))
  x1 x2 value
1  a  a    30
2  b  a     9
3  a  b    27
4  b  b     6
> transform(dfr,val1=x[x1],val2=x[x2])
  x1 x2 value val1 val2
1  a  a    30    5    5
2  b  a     9    2    5
3  a  b    27    5    2
4  b  b     6    2    2
fhg3lkii

fhg3lkii5#

请看我对最近一个问题的回答。本质上,您使用环境来实现这种类型的功能。
对于更高维的情况,如果你想用简单的语法来检索结果(你可以命名行和列),你最好使用array(二维的),作为一种选择,你可以用一个不出现在其中的分隔符将两个键paste放在一起,然后将其作为一个唯一的标识符。
具体来说,是这样的:

tmp<-data.frame(x=c("a", "b"), val=c(5,2))
tmp2<-outer(seq(nrow(tmp)), seq(nrow(tmp)), function(lhs, rhs){tmp$val[lhs] + tmp$val[rhs]})
dimnames(tmp2)<-list(tmp$x, tmp$x)
tmp2
tmp2["a", "b"]
ggazkfy8

ggazkfy86#

使用tidyverse

使用更新的tidyverse方法添加答案。
可能有更干净的方法来处理crossing(它创建所有组合)和unnest ing,但这是一种快速而肮脏的方法。

library(tidyverse)

my_tbl <- tibble(x = c("A", "B"), val=c(5,2)) %>% 
  crossing(x1 = ., x2 = .) %>%  # Create all combinations
  unnest_wider(everything(), names_sep="_") %>% # Unpack into distinct columns
  mutate(result = x1_val^2 + x2_val)  # Calculate result

# Access result by accessing the row in the data frame
my_tbl %>% 
  filter(x1_x == "A", x2_x == "B") %>% 
  pull(result)
#> [1] 27

# Convert tibble to a named vector that could be accessed more easily.
# However, this is limited to string names.
my_named_vector <- my_tbl %>% 
  transmute(name = str_c(x1_x, "_", x2_x), value=result) %>% 
  deframe()

my_named_vector[["A_B"]]
#> [1] 27

reprex package(v2.0.1)于2022年4月6日创建
tibble版本3.1.6
dplyr版本1.0.8
tidyr版本1.2.0
stringr版本1.4.0

相关问题