代码之家  ›  专栏  ›  技术社区  ›  Vishesh Shrivastav Akitha_MJ

将计算列添加到数据帧r

  •  4
  • Vishesh Shrivastav Akitha_MJ  · 技术社区  · 7 年前

    我想从一个数据帧中计算一些列的统计数据(平均值、最小值、最大值、标准差等),并将这些值存储为另一个数据帧。

    下面是一个示例:

    >foo
    
        Col1 Col2 Col3 Col4
    1    1    6   10   60
    2    2    7   20   70
    3    3    8   30   80
    4    4    9   40   90
    5    5   10   50  100
    

    例如,我想将col1和col3的平均值和最小值存储在如下数据帧中:

    >bar
    
               Col1       Col3
    Mean          3         30
    Min           1         10
    

    我想通过一个循环,像这样:

    # Result dataframe
    bar <- data.frame(Col1 = integer(), Col3 = integer())
    
    variables_for_stats <- c("Col1","Col3")
    
    # I want to do something on the lines of this:
    for (z in variables_for_stats){
    
        # Populate column with required values
        col <- c(mean(foo$z,min(foo$z)) # Throws an error - argument is not numeric or logical: returning NA
    
        # Add col to 'bar'
        bar$z<- col # Does not work
    }
    

    我的实际foo数据帧目前有大约40列,而实际变量的统计值大约为20。这两者都可以改变,因此希望通过for循环和列表来实现这一点。我该怎么做?

    4 回复  |  直到 7 年前
        1
  •  3
  •   akrun    7 年前

    我们可以在感兴趣的列上循环,得到 mean min

    sapply(foo[c('Col1', 'Col3')], function(x) c(Mean = mean(x), Min =min(x)))
    #      Col1 Col3
    #Mean    3   30
    #Min     1   10
    

    注:基于应用的解决方案也是一个循环。但是,它比 for 循环理解输出

        2
  •  3
  •   giocomai    7 年前

    如果你对 tidyverse 解决方案…

    library(tidyverse)
    
    foo <- tribble(~Col1, ~Col2, ~Col3, ~Col4,
                   1,    6,   10,   60,
                   2,    7,   20,   70,
                   3,    8,   30,   80,
                   4,    9,   40,   90,
                   5,   10,   50,  100)
    
    foo %>%
      gather(Col, Value) %>% 
      group_by(Col) %>% 
      summarise(Mean = mean(Value), Minimum = min(Value))
    #> # A tibble: 4 x 3
    #>   Col    Mean Minimum
    #>   <chr> <dbl>   <dbl>
    #> 1 Col1      3       1
    #> 2 Col2      8       6
    #> 3 Col3     30      10
    #> 4 Col4     80      60
    

    编辑 如果希望得到的数据帧与您在问题中指出的完全一致,则:

    foo %>%
      gather(Col, Value) %>% 
      group_by(Col) %>% 
      summarise(Mean = mean(Value),
                Minimum = min(Value)) %>% 
      gather(Func, Value, 2:3) %>% 
      spread(Col, Value) %>% 
      select(Func, Col1, Col3)
    
    # A tibble: 2 x 3
    #  Func     Col1  Col3
    #  <chr>   <dbl> <dbl>
    #1 Mean        3    30
    #2 Minimum     1    10
    
        3
  •  2
  •   Onyambu    7 年前

    使用base r,可以执行以下操作:

    aggregate( values~ind,stack(foo),function(x)
         c(mean=mean(x),sd=sd(x),min=min(x),max=max(x)))#Write all the functions you want
       ind values.mean  values.sd values.min values.max
    1 Col1    3.000000   1.581139   1.000000   5.000000
    2 Col2    8.000000   1.581139   6.000000  10.000000
    3 Col3   30.000000  15.811388  10.000000  50.000000
    4 Col4   80.000000  15.811388  60.000000 100.000000
    

    如果您只需要摘要统计信息,那么:

     library(tidyverse)
     summary(foo)%>%
         data.frame()%>%
         select(-Var1)%>%
         separate(Freq,c("Fun","Val"),":")%>%
         spread(Fun, Val)
    
           Var2 1st Qu. 3rd Qu. Max.    Mean    Median  Min.   
    1      Col1     2       4       5       3       3       1  
    2      Col2     7       9      10       8       8       6  
    3      Col3    20      40      50      30      30      10  
    4      Col4    70      90     100      80      80      60  
    
        4
  •  1
  •   Calum You    7 年前

    你可以这样做 tidyverse 工具。实际的计算是 summarise ,其余的只是将输出转换为所需的格式。

    library(tidyverse)
    foo <- read_table2(
      "Col1 Col2 Col3 Col4
    1    6   10   60
    2    7   20   70
    3    8   30   80
    4    9   40   90
    5   10   50  10"
    )
    
    bar <- foo %>%
      summarise_at(
        .vars = vars(Col1, Col3),
        .funs = funs(mean, min)
      ) %>%
      gather(stat, value) %>%
      separate(stat, into = c("Col", "Func")) %>%
      spread(Col, value)
    bar
    #> # A tibble: 2 x 3
    #>   Func   Col1  Col3
    #>   <chr> <dbl> <dbl>
    #> 1 mean      3    30
    #> 2 min       1    10
    

    于2018-06-04由 reprex package (v0.2.0)。