2017-07-03 11 views
10

Próbuję użyć dplyr::case_when w obrębie dplyr::mutate, aby utworzyć nową zmienną, w której ustawiam niektóre wartości na brakujące i przekodowuję inne wartości jednocześnie.Unikanie konfliktu typów z dplyr :: case_when

Jednak gdy próbuję ustawić wartości NA, dostaję błąd mówiąc, że nie możemy tworzyć zmienne new ponieważ NA s są logiczne:

Error in mutate_impl(.data, dots) :
Evaluation error: must be type double, not logical.

Czy istnieje sposób, aby ustawić wartości NA w nielogiczny wektor w ramce danych wykorzystującej to?

library(dplyr)  

# Create data 
df <- data.frame(old = 1:3) 

# Create new variable 
df <- df %>% dplyr::mutate(new = dplyr::case_when(old == 1 ~ 5, 
                old == 2 ~ NA, 
                TRUE ~ old)) 

# Desired output 
c(5, NA, 3) 

Odpowiedz

10

Jak powiedział w ?case_when:

All RHSs must evaluate to the same type of vector.

rzeczywiście mają dwie możliwości:

1) Utwórz new jako wektor numerycznej

df <- df %>% mutate(new = case_when(old == 1 ~ 5, 
            old == 2 ~ NA_real_, 
            TRUE ~ as.numeric(old))) 

Zauważ, że NA_real_ jestnumeryczną wersję NA i musisz przekonwertować numer old na numeryczny, ponieważ utworzyłeś go jako liczbę całkowitą w oryginalnej ramce danych.

Otrzymasz:

str(df) 
# 'data.frame': 3 obs. of 2 variables: 
# $ old: int 1 2 3 
# $ new: num 5 NA 3 

2) Tworzenie new jako wektor liczb całkowitych

df <- df %>% mutate(new = case_when(old == 1 ~ 5L, 
            old == 2 ~ NA_integer_, 
            TRUE ~ old)) 

Tutaj 5L siły 5 do typu całkowitego i NA_integer jest wersja całkowitą NA.

Więc tym razem new jest liczbą całkowitą:

str(df) 
# 'data.frame': 3 obs. of 2 variables: 
# $ old: int 1 2 3 
# $ new: int 5 NA 3 
+2

Można również zrobić 'as.numeric (NA)' lub 'as.integer (NA)' na 'przypadkach NA', jak i' NA_real_' 'NA_integer_' są nieco denerwujące do zapamiętania i rzadko używane poza takimi rzeczami. – Marius

+0

Nice. Ponadto, aby pokazać: identyczne (NA_real_, as.numeric (NA)) daje TRUE. – user3614648

+0

@hadley Ta odpowiedź jest teraz dla mnie jasna, ale zajęło mi to trochę czasu. Byłoby bardzo pomocne mieć przykład tego w tidyverse 'case_when' dokumentacji. W moim przypadku, gdy brakowało wszystkich wartości dla zgrupowanych danych, średnia (x [1: 2], na.rm = T) generowała wynik NaN. przekodowanie tych przypadków na NA_real_ naprawiło to. –

2

Spróbuj tego?

df %>% dplyr::mutate(new = dplyr::case_when(.$old == 1 ~ 5, 
                .$old == 2 ~ NA_real_, 
                TRUE~.$old)) 

> df 
    old new 
1 1 5 
2 2 NA 
3 3 3