Search code examples
rlistdataframematrixmatching

Matching values between a vector and a list within a matrix, then sampling from another list in the same matrix using the index from the match in R?


Sorry, I'm a bit jumbled in my thoughts to ask this in any articulate manner. My apologies if this doesn't make total sense. Also I'm mostly self-taught with R, so if I don't do something very efficiently, please forgive me and feel free to correct as needed.

I have data that include information about objects that children touch and what percentage of their hand is typically in contact with the object. For example, if a child is touching an animal, anywhere from 2% to 27% of their hand is in physical contact with the animal's fur, with a normally distributed probability of any fractional surface areas within this range occurring for each individual time a child touches the animal which, let's say, happens 2 different times within a minute. In between touching the animal, they are also touching other objects, which have their own distributions for the fractional surface area contact.

bodypart object
Left_hand Animal
Left_hand Fabric_Toy
Right_hand Nothing
Left_hand Fabric_Toy
Right_hand Clothes
Right_hand Animal

Basically what I want to do is take a dataframe that I have that contains a column with the object that the child is touching, match it to the object in the first list within the distribution matrix, and then randomly sample one value from the second list that contains the fractional surface area distributions from the same index as the matched value in the first list to then be placed in a column in the dataframe called "FSA."

My actual dataframe and matrix are much larger, but here is a small example:

#Here's my dataframe containing the objects that the kid is actually touching throughout the day
bodypart <- c("Left_hand", "Left_hand", "Right_hand", "Left_hand", "Right_hand")
object <- c("Animal", "Fabric_Toy", "Nothing", "Fabric_Toy", "Clothes", "Animal")
df <- data.frame(cbind(bodypart, object))

#Here's the list of objects and their matching distributions
Animal <- c("Animal")
Animal_Dist <- rnormTrunc(10, mean=0.10, sd=0.08, min=0.02, max=0.27)

Fabric <- c("Fabric_Toy", "Clothes")
Fabric_Dist <- rlnormTrunc(10, meanlog=0.10, sdlog=0.08, min=0, max=Inf)

Full_Immersion <- c("Nothing")
Full_Immersion_Dist <- runif(10, min=1, max=1) #Cheesy I know, but in keeping with the pattern...

#And now building my matrix of these lists
objects.list <- list(Animal, Fabric, Full_Immersion)
dist.list <- list(Animal_Dist, Fabric_Dist, Full_Immersion_Dist)
dist.matrix <- cbind(objects.list, dist.list)

#I was able to find the matching object values using this code
which(sapply(dist.matrix, function(dist.list) df$object[[1]] %in% dist.list))

From here, I would need to create a new column, df$FSA, where I sample from dist.list from the same index that was found using which(sapply(dist.matrix, function(dist.list) df$object[[i]] %in% dist.list)) for each row of df.

bodypart object FSA
Left_hand Animal 0.16287777
Left_hand Fabric_Toy 1.1249943
Right_hand Nothing 1
Left_hand Fabric_Toy 1.1701766
Right_hand Clothes 1.2117568
Right_hand Animal 0.15189102

Oye, sorry if this was hard to follow. Thank you all so much for your help!

Edit: Here is what I have so far. It feels close, but not quite where it needs to be.

for (i in 1:nrow(df)){
  for (j in 1:nrow(dist.matrix)){
    for (k in 1:length(dist.list)){
      df$FSA[[i]] <- ifelse(df$object[[i]] == dist.matrix[,"objects.list"][k], sample(dist.matrix[,"dist.list"][k], 1), NA)
    }
  }
}

Solution

  • Figured it out myself. Thought I'd share in case anyone has feedback or the same question.

    for (i in 1:nrow(df)){
      for (j in 1:nrow(dist.matrix)){
        temp.list1 <- dist.matrix[[j,1]]
        for (k in 1:length(temp.list1)){
          if(df$object[[i]] == temp.list1[k]){
            temp.list2 <- dist.matrix[[j, 2]]
            df$FSA[[i]] <- sample(temp.list2, size=1)
          }
        }
      }
    }