Search code examples
rfor-loopif-statementsapply

Program that inputs observation into a vector based on intersection of three observations


Hello I am having difficulty with finding a solution to a program I have been writing and could use some support.

The objective is to create a new parameter called Lambda for each person in my data set. Lambda is a function of 3 observations found in Df_obvs: Row, OAlpha, OSigma.

Row determines the data.frame used to find Lambda while the OSigma and OAlpha observations identify the row and column that identifies the individuals Lambda parameter. There are 3 possible "Row" options: 1, 2, and 3 so there are 3 possible data frames: Row1, Row2, and Row3. It is important to state in my real problem Row1[1,1]!=Row2[1,1] however for this example you will notice that Row1=Row2=Row3.

#create observation matrix
Names<-c('Bob','Jane','Sue')
Row<-c(1,2,3)
OAlpha<-c(.05,.75,1.5)
OSigma<-c(.1,.9,1.4)
Df_obvs<-cbind.data.frame(Names,OAlpha,OSigma,Row)

Creation of the data frames used to identify the Lambda parameters.

Switch<-data.frame(replicate(30,sample(0:8,30,rep=TRUE)))
alpha<-seq(.05,1.5,.05)
sigma<-seq(.05,1.5,.05)
colnames(Switch)<-alpha
rownames(Switch)<-sigma

Row1<-Switch
Row2<-Switch
Row3<-Switch

This is where my challenge lies. I would like to have the program check the individuals observation for Row in order to identify which data frame (Row1, Row 2, or Row 3) to use to determine Lambda. Then use the observations OSigma and OAlpha to locate the exact cell in the data frame and set Lambda[j] equal to that.

final_lambda<- matrix(NA,3,1)
for (j in 1:length(Df_obvs[,1])){
       if (Df_obvs$Row[j]==1) {Lambda[j]<-sapply(1:nrow(Df_obvs), function(i){Row1[Df_obvs$OSigma[i],Df_obvs$OAlpha[i]]})}
  else if (Df_obvs$Row[j]==2) {Lambda[j]<-sapply(1:nrow(Df_obvs), function(i){Row2[Df_obvs$OSigma[i],Df_obvs$OAlpha[i]]})}
  else                        {Lambda[j]<-sapply(1:nrow(Df_obvs), function(i){Row3[Df_obvs$OSigma[i],Df_obvs$OAlpha[i]]})}}

I appreciate your time and look forward to seeing where I am going wrong. Please let me know if I should clarify anything.


Solution

  • If I got you right the following code should do what you want to achieve. Basic idea:

    1. Put your Row-dfs in a list (lists are always great if you have a bunch of similar dfs)
    2. Convert OAlpha and OSigma to character for indexing the Row-dfs by rowname and colname
    3. Get the lambda value of each individual (which I would simply put in the df as another var)
    set.seed(42)
    
    # Set up Switch
    Switch<-data.frame(replicate(30,sample(0:8,30,rep=TRUE)))
    alpha<-seq(.05,1.5,.05)
    sigma<-seq(.05,1.5,.05)
    colnames(Switch)<-alpha
    rownames(Switch)<-sigma
    
    Row1<-Switch
    Row2<-Switch
    Row3<-Switch
    
    # Put the dfs in a list
    Rows <- list(Row1, Row2, Row3)
    
    # Set up Df_obvs
    Df_obvs <- data.frame(
      Names = c("Bob", "Jane", "Sue"),
      Row = c(1, 2, 3),
      OAlpha = c(.05, .75, 1.5),
      OSigma = c(.1, .9, 1.4)
    )
    # Convert to character for indexing
    Df_obvs$OAlpha <- as.character(Df_obvs$OAlpha)
    Df_obvs$OSigma <- as.character(Df_obvs$OSigma)
    
    # Get Lambda values coresponding to df Row, OAlpha, OSigma
    
    # Using temporary variables 
    Df_obvs$Lambda <- sapply(1:nrow(Df_obvs), function(j) {
      Row <- Rows[[ Df_obvs$Row[[j]] ]]
      sigma <- Df_obvs$OSigma[[j]]
      alpha <- Df_obvs$OAlpha[[j]]
      Row[sigma, alpha]
    })
    Df_obvs
    #>   Names Row OAlpha OSigma Lambda
    #> 1   Bob   1   0.05    0.1      4
    #> 2  Jane   2   0.75    0.9      0
    #> 3   Sue   3    1.5    1.4      4
    
    # As a one liner
    Df_obvs$Lambda1 <- sapply(1:nrow(Df_obvs), function(j) Rows[[ Df_obvs$Row[[j]] ]][Df_obvs$OSigma[j], Df_obvs$OAlpha[j]])
    Df_obvs
    #>   Names Row OAlpha OSigma Lambda Lambda1
    #> 1   Bob   1   0.05    0.1      4       4
    #> 2  Jane   2   0.75    0.9      0       0
    #> 3   Sue   3    1.5    1.4      4       4
    

    Created on 2020-03-18 by the reprex package (v0.3.0)