Как извлечь имя столбца из фрейма данных, который будет использоваться в l oop? - PullRequest
2 голосов
/ 21 января 2020

Я хотел бы скопировать текст имен столбцов фрейма по одному в a для l oop. Кажется, мой код возвращает значения NULL из аргумента имени столбца.

В более широком смысле я хочу создать сводку по коэффициентам для каждого из нескольких столбцов.

# Create an example data frame
df <- data.frame( c( "a", "b", "c", "b", "c"), c( 6, 4, 10, 9, 11), c( 1, 3, 5, 3, 6))

colnames(df) <- c( "Group", "Num.Hats", "Num.Balls")

example data frame with each group member's number of hats and number of balls

Теперь я хочу l oop по столбцам два и три, создавая объект данных, хранящий сводную статистику по группам. Суть в том, чтобы взглянуть на то, как группы A, B и C отличаются друг от друга в отношении шаров и шляп.

Мой код выглядит следующим образом:

# Evaluate stats of each group
for (i in 2:3){
    assign(paste0("Eval.", colnames(df[[i]])), tapply(df[,i], df$Group, summary))
}

Я получаю один объект с именем "Eval." со сводной статистикой для Num.Balls. Чтобы было ясно, я бы хотел два объекта, один с именем Eval.Num.Hats и другой с именем Eval.Num.Balls.

Если colnames() не может использоваться таким образом, есть ли другая функция для достижения желаемого результата? Кроме того, я был бы открыт для другого решения, если l oop не требуется.

Ответы [ 3 ]

2 голосов
/ 21 января 2020

Вы можете полностью избежать for-l oop.

Объяснение:

Здесь, используя lapply Я зацикливаюсь по всем столбцам (используя их имена) для суммирования, кроме первого, который используется для группировки (смотрите, что возвращает names(df1)[-1]).

with функция в основном присоединяет фрейм данных, поэтому вам не нужно чтобы сделать dataframe$column, и вы можете просто ввести имя столбца.

by(variable to function, grouping variable, function) используется для применения summary по группам.

Нам нужно использовать имя столбца как переменную, а не как символ. Вот почему я использую mget() для преобразования имени символа столбца в переменную.

smry.ls.df1 <- lapply(names(df1)[-1], function(col) with(df1, by(mget(col), Group, summary)))
names(smry.ls.df1) <- paste0("Eval.", names(df1)[-1]) #setting the names as you've shown
smry.list.df1

#> $Eval.Num.Hats
#> Group: a
#>    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
#>       6       6       6       6       6       6 
#> -------------------------------------------------------- 
#> Group: b
#>    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
#>    4.00    5.25    6.50    6.50    7.75    9.00 
#> -------------------------------------------------------- 
#> Group: c
#>    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
#>   10.00   10.25   10.50   10.50   10.75   11.00 
#> 
#> $Eval.Num.Balls
#> Group: a
#>    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
#>       1       1       1       1       1       1 
#> -------------------------------------------------------- 
#> Group: b
#>    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
#>       3       3       3       3       3       3 
#> -------------------------------------------------------- 
#> Group: c
#>    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
#>    5.00    5.25    5.50    5.50    5.75    6.00

Если вы хотите, чтобы они были сохранены как отдельные объекты (не рекомендуется), вы можете использовать list2env:

list2env(smry.list.df1, globalenv())

Данные:

df1 <- data.frame(Group = c( "a", "b", "c", "b", "c"), 
                  Num.Hats = c( 6, 4, 10, 9, 11), 
                  Num.Balls = c( 1, 3, 5, 3, 6))
2 голосов
/ 21 января 2020

df[[i]] извлекает столбец как vector, а colnames нет. Мы можем использовать df[i] или правильный параметр colnames(df)[i]

for (i in 2:3){
    assign(paste0("Eval.", colnames(df)[i]), tapply(df[,i], df$Group, summary))
 }

-output

Eval.Num.Hats
#$a
#   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
#      6       6       6       6       6       6 

#$b
#   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
#   4.00    5.25    6.50    6.50    7.75    9.00 

#$c
#   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
#  10.00   10.25   10.50   10.50   10.75   11.00 

Eval.Num.Balls
#$a
#   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
#      1       1       1       1       1       1 

#$b
#   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
#      3       3       3       3       3       3 

#$c
#   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
#   5.00    5.25    5.50    5.50    5.75    6.00 
1 голос
/ 22 января 2020

Вот еще одно решение без петель, использующее tidyr и broom.

library(tidyr)
library(broom)

df %>%
  #Change from wide to long format
  pivot_longer(cols = c("Num.Hats","Num.Balls"),
               names_to = "Var") %>%
  #group by Group (a,b,c) and Var (Num.Hats, Num.Balls)
  group_by(Group, Var) %>%
  #Calculate the summary function for each group
  do(tidy(summary(.$value)))

# A tibble: 6 x 8
# Groups:   Group, Var [6]
#  Group Var    minimum    q1 median  mean    q3 maximum
#  <fct> <chr>    <dbl> <dbl>  <dbl> <dbl> <dbl>   <dbl>
#1 a     Num.B~       1  1       1     1    1          1
#2 a     Num.H~       6  6       6     6    6          6
#3 b     Num.B~       3  3       3     3    3          3
#4 b     Num.H~       4  5.25    6.5   6.5  7.75       9
#5 c     Num.B~       5  5.25    5.5   5.5  5.75       6
#6 c     Num.H~      10 10.2    10.5  10.5 10.8       11
...