Assigning elements of one vector to elements of another with R

Viewed 369

I would like to assign elements of one vector to elements of another for every single user.

For example:

Within a data frame with the variables "user", "activities" and "minutes" (see below), I would like to assign, for example, the duration (4 minutes) of the first activity (4 minutes to activity "READ") of user 1 to new variable READ_duration. Then duration (5 minutes) of second activity ("EDIT") to the new variable EDIT_duration. And the duration (2 minutes) of third activity (again "READ") to the new variable READ_duration.

user <- 1,2,3

activities <- c("READ","EDIT","READ"), c("READ","EDIT", "WRITE"), c("WRITE","EDIT")

minutes <- c(4,5,2), c(3.5, 1, 2), c(4.5,3)

Output should be like: in a data frame with the assigned minutes to the activities:

user READ_duration EDIT_duration WRITE_duration

1        6               5                0
2        3.5             1                2
3        0               3                4.5    

The tricky thing here is the algorithm needs to consider that the activities are not in the same order for every user. For example, user 3 starts with writing and therefore the duration 4.5 needs to be assigned to column 4 WRITE_duration.

Also, a loop-function would be needed due to a massive amount of users.

Thank you so much for your help!!

2 Answers

This needs a simple reshape to wide format with sum as an aggregation function.

Prepare a long-format data.frame:

user <- c(1,2,3)

activities <- list(c("READ","EDIT","READ"), c("READ","EDIT", "WRITE"), c("WRITE","EDIT"))

minutes <- list(c(4,5,2), c(3.5, 1, 2), c(4.5,3))


DF <- Map(data.frame, user = user, activities = activities, minutes = minutes)
DF <- do.call(rbind, DF)
#  user activities minutes
#1    1       READ     4.0
#2    1       EDIT     5.0
#3    1       READ     2.0
#4    2       READ     3.5
#5    2       EDIT     1.0
#6    2      WRITE     2.0
#7    3      WRITE     4.5
#8    3       EDIT     3.0

Reshape:

library(reshape2)
dcast(DF, user ~ activities, value.var = "minutes", fun.aggregate = sum)
#  user EDIT READ WRITE
#1    1    5  6.0   0.0
#2    2    1  3.5   2.0
#3    3    3  0.0   4.5

in base R you could do:

xtabs(min~ind+values, cbind(stack(setNames(activities, user)), min = unlist(minutes)))
   values
ind EDIT READ WRITE
  1  5.0  6.0   0.0
  2  1.0  3.5   2.0
  3  3.0  0.0   4.5
Related