Rock
Rock

Reputation: 2977

Obtain values through key vector (R)

This actually corresponds to my other question but things get more complicated. I have data.frame and vector:

df <- data.frame(key=c(0,3:6), value=c(0,52,26,12,1))
x <- c(3,4,3,3,5,5,6,6,6,6)

and need to obtain values from df based on x as keys:

[1] 52 26 52 52 12 12 1 1 1 1

Solution from previous answer can only give result with NO duplicates:

df[df$key %in% x,"value"]
[1] 52 26 12  1

Is there a way to solve this?

Also, I see hash() can do things like:

h <- hash( keys=letters, values=1:26 )
h$a # 1
h[ "a" ]
h[[ "a" ]]

z <- rep(letters[3:5],2)

h[z] # still with NO duplicates
<hash> containing 3 key-value pair(s).
c : 3
d : 4
e : 5

But seems like it cannot return a vector of values with something like:

h[[z]]
Error in h[[z]] : wrong arguments for subsetting an environment

Otherwise, it would be perfect so that we can get rid of data.frame by using some 'real' hash concept.

Thanks!

Upvotes: 5

Views: 3321

Answers (3)

jthetzel
jthetzel

Reputation: 3623

I'm not sure if this is the best way, but merge() will get you there:

df <- data.frame(key=c(0,3:6), value=c(0,52,26,12,1))
x <- c(3,4,3,3,5,5,6,6,6,6)

merge(x, df, by.x="x", by.y = "key")
#    x value
# 1  3    52
# 2  3    52
# 3  3    52
# 4  4    26
# 5  5    12
# 6  5    12
# 7  6     1
# 8  6     1
# 9  6     1

Update Regarding your question on hash(), would something like the following do for now?

hashMatch <- function(x, y)
{
    laply(y, function(z)
        {
            x[[z]]
        })
}

require(plyr)
require(hash)

h <- hash( keys=letters, values=1:26 )
z <- rep(letters[3:5],2)

hashMatch(h, z)
# [1] 3 4 5 3 4 5

Upvotes: 2

Andrie
Andrie

Reputation: 179558

To answer your first question: Use match

df[match(x, df$key), ]

    key value
2     3    52
3     4    26
2.1   3    52
2.2   3    52
4     5    12
4.1   5    12
5     6     1
5.1   6     1
5.2   6     1
5.3   6     1

You should also have a look at Named vectors

dat <- c(0,52,26,12,1)
names(dat) <- as.character(c(0,3:6))

dat[as.character(x)]
 3  4  3  3  5  5  6  6  6  6 
52 26 52 52 12 12  1  1  1  1 

Upvotes: 3

James
James

Reputation: 66874

You can use match to select your values:

df[match(x,df$key),"value"]
[1] 52 26 52 52 12 12  1  1  1  1

Upvotes: 2

Related Questions