简体   繁体   中英

Iterate a data frame containing lists of column numbers, of different lengths, with a function in R

I have a data frame (df) of survey responses about human values with 57 columns/variables of numerical/scale responses. Each column belongs to one of ten categories, and they're not in contiguous groups.

I have a second dataframe (scoretable) that associates the categories with the column numbers for the variables; the lists of column numbers are all different lengths:

scoretable <- data.frame(
     valuename = 
     c("Conformity","Tradition","Benevolence","Universalism","Self- 
     Direction","Stimulation","Hedonism","Achievement","Power","Security"),
     valuevars = I(list(c(11,20,40,47), # Conformity
                        c(18,32,36,44,51), # Tradition
                        c(33,45,49,52,54), # Benevolence
                        c(1,17,24,26,29,30,35,38), # Universalism
                        c(5,16,31,41,53), # Self-Direction
                        c(9,25,37), # Stimulation
                        c(4,50,57), # Hedonism
                        c(34,39,43,55), # Achievement
                        c(3,12,27,46), # Power
                        c(8,13,15,22,56))), # Security
     stringsAsFactors=FALSE)

I would like to iterate through scoretable with a function, valuescore, that calculates the mean and sd of all responses in that group of columns in data frame df and write the result to a third table of results:

valuescore = function(df,scoretable,valueresults){
    valuename = scoretable[,1]
    set <- df[,scoretable[,2]]
    setmeans <- colMeans(set,na.rm=TRUE)
    valuemean <- mean(setmeans)
    setvars <- apply(set, 2, var)
    valuesd <-sqrt(mean(setvars))
    rbind(valueresults,c(valuename, valuemean, valuesd))
}

a <- nrow(scoretable)
for(i in 1:a){
    valuescore(df,scoretable[i,],valueresults)
}

I am very new to R and programming in general (this is my first question here), and I'm struggling to determine how to pass list variables to functions and/or as address ranges for data frames.

Let's create an example data.frame:

df <- replicate(57, rnorm(10, 50, 20)) %>% as.data.frame()

Let's prepare the table result format:

valueresults <- data.frame(
  name = scoretable$valuename, 
  mean = 0
)

Now, a loop on the values of scoretable, a mean calculation by column and then the mean of the mean. It is brutal (first answer with Map is more elegant), but maybe it is easier to understand for a R beginnner.

for(v in 1:nrow(scoretable)){
  # let's suppose v = 1 "Conformity"
  columns_id <- scoretable$valuevars[[v]]

  # isolate columns that correspond to 'Conformity'
  temp_df    <- df[, columns_id]

  # mean of the values of these columns
  temp_means <- apply(temp_df, 2, mean)
  mean       <- mean(temp_means)

  # save result in the prepared table
  valueresults$mean[v] <- mean
}

> (valueresults)
             name     mean
1      Conformity 45.75407
2       Tradition 52.76935
3     Benevolence 50.81724
4    Universalism 51.04970
5  Self-Direction 55.43723
6     Stimulation 52.15962
7        Hedonism 53.17395
8     Achievement 47.77570
9           Power 52.61731
10       Security 54.07066

Here is a way using Map to apply a function to the list scoretable[, 2] .

First I will create a test df .

set.seed(1234)
m <- 100
n <- 57
df <- matrix(sample(10, m*n, TRUE), nrow = m, ncol = n)
df <- as.data.frame(df)

And now the function valuescore .

valuescore <- function(DF, scores){
  f <- function(inx) mean(as.matrix(DF[, inx]), na.rm = TRUE)
  res <- Map(f, scores[, 2])
  names(res) <- scores[[1]]
  res
}

valuescore(df, scoretable)
#$Conformity
#[1] 5.5225
#
#$Tradition
#[1] 5.626
#
#$Benevolence
#[1] 5.548
#
#$Universalism
#[1] 5.36125
#
#$`Self-Direction`
#[1] 5.494
#
#$Stimulation
#[1] 5.643333
#
#$Hedonism
#[1] 5.546667
#
#$Achievement
#[1] 5.3175
#
#$Power
#[1] 5.41
#
#$Security
#[1] 5.54

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM