1

Suppose I have a data frame like the following

a=data.frame(x=1:3,y=c("a","b","c"))

where y is the key column. Sometimes I just want to look up a the value of x corresponding to a key in y. To accomplish this, I can

row.names(a)=a$y
a["b",c("x")]

Just like looking up a value of a given key in a Python dictionary.

Now I want to achieve the same thing using tidyverse's tibble. But since tibble does not have row.names, I have no idea how to do it.

My question is, what is the "most clever" way (or idiomatic way, to borrow a term from Python) to look up a single value in a tibble given a single key?

wdg
  • 1,687
  • 5
  • 17
  • 29
  • Try `rownames_to_column(a, 'rn') %>% filter(rn == 'b') %>% select(x)` – akrun Jul 10 '18 at 17:05
  • 2
    You're asking for `tidyverse` solution, but for the record - this is pretty convenient with `data.table`: `setkey(setDT(a), y)` and then just `a["b"]` – pogibas Jul 10 '18 at 17:08
  • 2
    A dataframe isn't the best way of representing this type of data, keys can be duplicated. You could use a named list – Jack Brookes Jul 10 '18 at 17:13
  • @JackBrookes Names can be duplicated too, e.g, `names(list(a = 1, a = 2))`, so I don't think a named list is really an improvement over a data.frame. – Ista Jul 10 '18 at 17:47
  • You seem to want the behavior of a hash table for item look up. That's not a a basic class in R and it's not a very "tidy" way of working with data, but there are techniques you can use. Possible duplicate: https://stackoverflow.com/questions/8299367/natural-way-to-represent-hash-tables-dictionaries-maps-in-r. The "idiomatic" way to do this in R is to not do many single item looks up, just do a merge or something. Had to say for sure since you don't talk much about why you want to do this in the first place. – MrFlick Jul 10 '18 at 18:16
  • or: `filter(a, y == 'b') %>% pull(x)` – Jaap Jul 10 '18 at 18:24
  • @MrFlick I'm well aware of the solution using environment. I just wanted to know how to do the same thing in tidyverse efficiently. My workflow can be implemented in tidyverse elegantly, except the part where a dictionary-like look-up is involved. – wdg Jul 11 '18 at 05:15

2 Answers2

2

Either of

filter(a, y == "b")$x

or

a[a$y == "b", "x"]

would be fine I think.

Ista
  • 10,139
  • 2
  • 37
  • 38
0

What you can do is use something like this

mapping <- function(key, dictionary) {
  values <- dictionary[key, ]
  return(values)
}

mapping('b', a)

And here is the bonus if the dictionary is a tibble without rownames, you can do

mapping <- function(keys, dictionary) {
  keys <- tibble::tibble(key=keys)
  dictionary <- tibble::tibble(key=dictionary[[1]], value=dictionary[[2]])
  values <- dplyr::left_join(keys, dictionary, by='key') %>% dplyr::select('value') %>% dplyr::pull()
  return(values)
}

Those mapping functions will also work when you x is a vector.

Chunhui Gu
  • 29
  • 5