str (df) выглядит иначе после итерации функции, почему? - PullRequest
0 голосов
/ 27 марта 2020

После запуска итерации функции str(df) выглядит иначе (см. Ниже). Позже у меня возникают проблемы с анализом, и я думаю, что это вызывает проблему. Но я не знаю, почему это произошло и как это можно исправить?

id <- factor(rep(letters[1:2], each=5))
    A <- c(1,2,NA,6,8,9,0,6,7,9)
    B <- c(5,6,1,9,8,1,NA,9,7,4)
    C <- c(2,3,5,NA,NA,2,7,6,4,6)
    D <- c(6,5,8,3,2,9,NA,2,6,8)
    df <- data.frame(id, A, B,C,D) 
    df


dat <- data.frame(col=c("A","B","C","D"), value=c(23,45,26,89))

test <- function(i){
  df[,i][is.na(df[,i])] <- dat$value[dat$col==i]
  return(df[i])
}
df <-df[,-1]

for(i in colnames(df)){
  df[[i]] <- test(i)
}
df 

str(df)

'data.frame':   10 obs. of  4 variables:
 $ A:'data.frame':  10 obs. of  1 variable:
  ..$ A: num  1 2 23 6 8 9 0 6 7 9
 $ B:'data.frame':  10 obs. of  1 variable:
  ..$ B: num  5 6 1 9 8 1 45 9 7 4
 $ C:'data.frame':  10 obs. of  1 variable:
  ..$ C: num  2 3 5 26 26 2 7 6 4 6
 $ D:'data.frame':  10 obs. of  1 variable:
  ..$ D: num  6 5 8 3 2 9 89 2 6 8

Почему это не выглядит так:

 'data.frame':  10 obs. of  5 variables:
     $ id: Factor w/ 2 levels "a","b": 1 1 1 1 1 2 2 2 2 2
     $ A : num  1 2 23 6 8 9 0 6 7 9
     $ B : num  5 6 1 9 8 1 45 9 7 4
     $ C : num  2 3 5 26 26 2 7 6 4 6
     $ D : num  6 5 8 3 2 9 NA 2 6 8

Благодарим Вас за помощь.

Ответы [ 2 ]

3 голосов
/ 27 марта 2020

Потому что ваш l oop преобразовал его в список. Вы можете переключить его обратно в фрейм данных таким образом:

df <- as.data.frame.list(df)

str(df)    
'data.frame':   10 obs. of  4 variables:
 $ A: num  1 2 23 6 8 9 0 6 7 9
 $ B: num  5 6 1 9 8 1 45 9 7 4
 $ C: num  2 3 5 26 26 2 7 6 4 6
 $ D: num  6 5 8 3 2 9 89 2 6 8
2 голосов
/ 27 марта 2020

str(df) теперь возвращает что-то другое, потому что вы создали кадр данных столбцов, вложенных в свои собственные кадры данных, а не кадр данных с плоскими столбцами.

Похоже, то, что вы пытаетесь сделать, это просто замените NA значением из вашего списка dat. Функция tidyr replace_na чрезвычайно полезна для такого рода вещей, и вам не придется определять какие-либо функции или вызывать for l oop:

library(tidyr) # you'll need to install if you don't have it
library(tidyverse) # highly recommended as well

id <- factor(rep(letters[1:2], each=5))
A <- c(1,2,NA,6,8,9,0,6,7,9)
B <- c(5,6,1,9,8,1,NA,9,7,4)
C <- c(2,3,5,NA,NA,2,7,6,4,6)
D <- c(6,5,8,3,2,9,NA,2,6,8)
df <- data.frame(id, A, B,C,D) 

str(df) # a simple, flat, dataframe

 >   Classes ‘tbl_df’, ‘tbl’ and 'data.frame':  10 obs. of  5 variables:
 >    $ id: Factor w/ 2 levels "a","b": 1 1 1 1 1 2 2 2 2 2
 >    $ A : num  1 2 NA 6 8 9 0 6 7 9
 >    $ B : num  5 6 1 9 8 1 NA 9 7 4
 >    $ C : num  2 3 5 NA NA 2 7 6 4 6
 >    $ D : num  6 5 8 3 2 9 NA 2 6 8

dat <- list("A" = 23, "B" = 45, "C" = 26, "D" = 89)

# replaces all the NA values in `df` using the key in `dat`
df <- replace_na(df, dat) 

str(df) # still a simple, flat dataframe

 >   Classes ‘tbl_df’, ‘tbl’ and 'data.frame':  10 obs. of  5 variables:
 >    $ id: Factor w/ 2 levels "a","b": 1 1 1 1 1 2 2 2 2 2
 >    $ A : num  1 2 23 6 8 9 0 6 7 9
 >    $ B : num  5 6 1 9 8 1 45 9 7 4
 >    $ C : num  2 3 5 26 26 2 7 6 4 6
 >    $ D : num  6 5 8 3 2 9 89 2 6 8

...