2017-08-24 49 views
5

Mam kilka ramek danych z różnymi zmiennymi. Chcę je odczytać do R i dodać kolumny do tych, które nie mają kilku zmiennych, tak aby wszystkie miały wspólny zestaw standardowych zmiennych, nawet jeśli niektóre są nieobserwowane.Dodawanie kolumny, jeśli nie istnieje

Innymi słowy ... Czy istnieje sposób dodawania kolumn NA w tidyverse, gdy kolumna nie istnieje? Moja obecna próba polega na dodaniu nowych zmiennych, gdy kolumna nie istnieje (top_speed), ale kończy się niepowodzeniem, gdy kolumna już istnieje (mpg) (ustawia wszystkie obserwacje na pierwszą wartość, Mazda RX4).

library(tidyverse) 
mtcars %>% 
    tbl_df() %>% 
    rownames_to_column("car") %>% 
    mutate(top_speed = ifelse("top_speed" %in% names(.), top_speed, NA), 
     mpg = ifelse("mpg" %in% names(.), mpg, NA)) %>% 
    select(car, top_speed, mpg, everything()) 

# # A tibble: 32 x 13 
#     car top_speed mpg cyl disp hp drat wt qsec vs am gear carb 
#    <chr>  <lgl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> 
# 1   Mazda RX4  NA 21  6 160.0 110 3.90 2.620 16.46  0  1  4  4 
# 2  Mazda RX4 Wag  NA 21  6 160.0 110 3.90 2.875 17.02  0  1  4  4 
# 3  Datsun 710  NA 21  4 108.0 93 3.85 2.320 18.61  1  1  4  1 
# 4 Hornet 4 Drive  NA 21  6 258.0 110 3.08 3.215 19.44  1  0  3  1 
# 5 Hornet Sportabout  NA 21  8 360.0 175 3.15 3.440 17.02  0  0  3  2 
# 6   Valiant  NA 21  6 225.0 105 2.76 3.460 20.22  1  0  3  1 
# 7  Duster 360  NA 21  8 360.0 245 3.21 3.570 15.84  0  0  3  4 
# 8   Merc 240D  NA 21  4 146.7 62 3.69 3.190 20.00  1  0  4  2 
# 9   Merc 230  NA 21  4 140.8 95 3.92 3.150 22.90  1  0  4  2 
# 10   Merc 280  NA 21  6 167.6 123 3.92 3.440 18.30  1  0  4  4 

Odpowiedz

3

Moglibyśmy utworzyć funkcję pomocniczą, aby utworzyć kolumnę

fncols <- function(data, cname) { 
    add <-cname[!cname%in%names(data)] 

    if(length(add)!=0) data[add] <- NA 
    data 
} 
fncols(mtcars, "mpg") 
fncols(mtcars, c("topspeed","nhj","mpg")) 
+1

... Dziękujemy, że to działa najszybciej z odpowiedziami tak daleko ... Mam zamiar używać go w sieci z wieloma (~ 15) zmienne ... 'mtcars%>% fncols ("mpg")%>% fncols ("top_speed") ' – gjabel

+1

zamiast używać go w łańcuchu, spójrz na edytowaną wersję – Onyambu

+0

@Onyambu Dzięki za edycję. Jest bardziej ogólny – akrun

1

Można użyć funkcji rowwise takiego:

library(tidyverse) 
mtcars %>% 
    tbl_df() %>% 
    rownames_to_column("car") %>% 
    rowwise() %>% 
    mutate(top_speed = ifelse("top_speed" %in% names(.), top_speed, NA), 
     mpg = ifelse("mpg" %in% names(.), mpg, NA)) %>% 
    select(car, top_speed, mpg, everything()) 
0

można powiązać kolumny nowej data.frame z fałszywym kompletnym danymi. Ramka wypełniona NA, zmiana nazwy zduplikowanych kolumn, a następnie filtrowanie tylko oryginalnych nazw.

# your default complete vector of col names 
standard.variables = names(mtcars) 
# prep 
default=mtcars %>% mutate_all(.funs=function(x) NA) 
# treat with a data.frame missing 3 columns 
test=mtcars %>% select(-mpg, -disp, -am) 
bind_cols(test, default) %>% setNames(make.names(names(.), unique=TRUE)) %>% 
    select_(.dots=standard.variables) %>% head(2) 
#### mpg cyl disp hp drat wt qsec vs am gear carb 
#### 1 NA 6 NA 110 3.9 2.620 16.46 0 NA 4 4 
#### 2 NA 6 NA 110 3.9 2.875 17.02 0 NA 4 4 
1

spróbuj wykonać następujące czynności,

library(tidyverse) 

mtcars %>% 
    tbl_df() %>% 
    rownames_to_column("car") %>% 
    mutate(top_speed = if ("top_speed" %in% names(.)){return(top_speed)}else{return(NA)}, 
     mpg = if ("mpg" %in% names(.)){return(mpg)}else{return(NA)}) %>% 
    select(car, top_speed, mpg, everything()) 
# A tibble: 32 x 13 
       car top_speed mpg cyl disp hp drat wt qsec vs am gear carb 
       <chr>  <lgl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> 
1   Mazda RX4  NA 21.0  6 160.0 110 3.90 2.620 16.46  0  1  4  4 
2  Mazda RX4 Wag  NA 21.0  6 160.0 110 3.90 2.875 17.02  0  1  4  4 
3  Datsun 710  NA 22.8  4 108.0 93 3.85 2.320 18.61  1  1  4  1 
4 Hornet 4 Drive  NA 21.4  6 258.0 110 3.08 3.215 19.44  1  0  3  1 
5 Hornet Sportabout  NA 18.7  8 360.0 175 3.15 3.440 17.02  0  0  3  2 
6   Valiant  NA 18.1  6 225.0 105 2.76 3.460 20.22  1  0  3  1 
7  Duster 360  NA 14.3  8 360.0 245 3.21 3.570 15.84  0  0  3  4 
8   Merc 240D  NA 24.4  4 146.7 62 3.69 3.190 20.00  1  0  4  2 
9   Merc 230  NA 22.8  4 140.8 95 3.92 3.150 22.90  1  0  4  2 
10   Merc 280  NA 19.2  6 167.6 123 3.92 3.440 18.30  1  0  4  4 
# ... with 22 more rows 

myślę ifelse() nie dziedziczy klasę od obiektu.

2

Jeśli dysponujesz pustą ramką danych zawierającą wszystkie nazwy do sprawdzenia, możesz użyć kolumny bind_rows.

Użyłem purrr:map_dfr, aby pusty tibble z odpowiednimi nazwami kolumn.

columns = c("top_speed", "mpg") %>% 
    map_dfr(~tibble(!!.x := logical())) 

# A tibble: 0 x 2 
# ... with 2 variables: top_speed <lgl>, mpg <lgl> 

bind_rows(columns, mtcars) 

# A tibble: 32 x 12 
    top_speed mpg cyl disp hp drat wt qsec vs am gear carb 
     <lgl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> 
1  NA 21.0  6 160.0 110 3.90 2.620 16.46  0  1  4  4 
2  NA 21.0  6 160.0 110 3.90 2.875 17.02  0  1  4  4 
3  NA 22.8  4 108.0 93 3.85 2.320 18.61  1  1  4  1