【问题标题】:Iterate a data frame containing lists of column numbers, of different lengths, with a function in R使用 R 中的函数迭代包含不同长度的列号列表的数据框
【发布时间】:2019-02-07 19:33:24
【问题描述】:

我有一个关于人类价值观的调查响应数据框 (df),其中包含 57 列/变量的数值/比例响应。每列属于十个类别之一,并且它们不在连续的组中。

我有第二个数据框(计分表),它将类别与变量的列号相关联;列号列表都是不同的长度:

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)

我想使用 valuescore 函数遍历 scoretable,该函数计算数据框 df 中该组列中所有响应的均值和 sd,并将结果写入第三个结果表:

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)
}

我对 R 和一般编程非常陌生(这是我在这里的第一个问题),我正在努力确定如何将列表变量传递给函数和/或作为数据帧的地址范围。

【问题讨论】:

    标签: r


    【解决方案1】:

    让我们创建一个示例 data.frame:

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

    让我们准备表格结果格式:

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

    现在,对 scoretable 的值进行循环,按列计算平均值,然后计算平均值。这很残酷(Map 的第一个答案更优雅),但对于 R 初学者来说可能更容易理解。

    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
    

    【讨论】:

    • 感谢您使用我已有的作品;正如您所说,“地图”的另一个解决方案很优雅,但这对我来说更容易获得。看到两者都是有价值的。感谢您的帮助!
    【解决方案2】:

    这是一种使用Map 将函数应用于列表scoretable[, 2] 的方法。

    首先我将创建一个测试df

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

    现在是函数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
    

    【讨论】:

    • 谢谢,这很优雅,帮助我了解函数如何适应函数,从而更有效地分解过程。第二个答案对我来说更容易理解,但看到两种方法真的很有帮助。
    猜你喜欢
    • 1970-01-01
    • 2020-03-30
    • 2018-02-02
    • 1970-01-01
    • 2020-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多