Zastąp wszystkie określone wartości w ramce danych

89

Mając ramkę danych, jak mam zastąpić wszystkie określone wartości we wszystkich wierszach i kolumnach. Załóżmy na przykład, że chcę zastąpić wszystkie puste rekordy NAsłowami (bez wpisywania pozycji):

df <- data.frame(list(A=c("", "xyz", "jkl"), B=c(12, "", 100)))

    A   B
1      12
2  xyz    
3  jkl 100

Spodziewany wynik:

    A   B
1  NA   12
2  xyz  NA  
3  jkl  100
zxzak
źródło

Odpowiedzi:

139

Lubię to:

> df[df==""]<-NA
> df
     A    B
1 <NA>   12
2  xyz <NA>
3  jkl  100
mrip
źródło
14
czy istnieje sposób na efektywne zrobienie tego dla więcej niż 1 wartości !?
PikkuKatja
28
To nie działa w przypadku czynników, df[df=="xyz"]<-"abc"spowoduje błąd z „nieprawidłowym poziomem czynnika”. Czy istnieje bardziej ogólne rozwiązanie?
glallen
1
nie działa dla mnie. Próbowałem tego: dfSmallDiscreteCustomSalary [dfSmallDiscreteCustomSalary $ salary == "<= 50 000"] <- "49 000". Nadal za unikalne (wynagrodzenie dfSmallDiscreteCustomSalary $) dostaję: [1]> 50
000
3
glallen ... jeśli próbujesz zmodyfikować kolumnę współczynnika nową wartością, która już jest czynnikiem, prawdopodobnie są bardziej sprytne sposoby niż to, co mam zamiar zasugerować, ale możesz df $ factorcolumn <- as.character ( df $ factorcolumn), a następnie dokonaj modyfikacji i zakończ, ponownie zmieniając ją w czynnik ... df $ factorcolumn <- as.factor (df $ factorcolumn); będzie kompletny z nowym poziomem i pożądaną wartością.
Joshua Eric Turcotte
Znalazłem to: df.na.replace (df.columns, Mapa ("" -> "NA")). Pokaż. Co ciekawe, nie jestem w stanie zastąpić null jako wartości. Otrzymuję: java.lang.IllegalArgumentException: Nieobsługiwany typ wartości java.lang.String (null). at org.apache.spark.sql.DataFrameNaFunctions.org $ apache $ spark $ sql $ DataFrameNaFunctions $$ convertToDouble (DataFrameNaFunctions.scala: 434)
sriram
34

Ponieważ PikkuKatja i glallen poprosili o bardziej ogólne rozwiązanie i nie mogę jeszcze komentować, napiszę odpowiedź. Możesz łączyć oświadczenia jak w:

> df[df=="" | df==12] <- NA
> df
     A    B
1  <NA> <NA>
2  xyz  <NA>
3  jkl  100

W przypadku czynników kod zxzak już daje czynniki:

> df <- data.frame(list(A=c("","xyz","jkl"), B=c(12,"",100)))
> str(df)
'data.frame':   3 obs. of  2 variables:
 $ A: Factor w/ 3 levels "","jkl","xyz": 1 3 2
 $ B: Factor w/ 3 levels "","100","12": 3 1 2

Jeśli masz kłopoty, sugerowałbym tymczasowe odrzucenie czynników.

df[] <- lapply(df, as.character)
sedot
źródło
18

Oto kilka dplyropcji:

library(dplyr)

# all columns:
df %>% 
  mutate_all(~na_if(., ''))

# specific column types:
df %>% 
  mutate_if(is.factor, ~na_if(., ''))

# specific columns:  
df %>% 
  mutate_at(vars(A, B), ~na_if(., ''))

# or:
df %>% 
  mutate(A = replace(A, A == '', NA))

# replace can be used if you want something other than NA:
df %>% 
  mutate(A = as.character(A)) %>% 
  mutate(A = replace(A, A == '', 'used to be empty'))
sbha
źródło
Jak zabrałbyś się za użycie rozwiązania wszystkich kolumn do zastąpienia kilku ciągów przez NA w całym zbiorze danych?
Tea Tree
4

Możemy skorzystać z data.table, aby to szybko uzyskać. Najpierw utwórz df bez współczynników,

df <- data.frame(list(A=c("","xyz","jkl"), B=c(12,"",100)), stringsAsFactors=F)

Teraz możesz użyć

setDT(df)
for (jj in 1:ncol(df)) set(df, i = which(df[[jj]]==""), j = jj, v = NA)

i możesz przekonwertować go z powrotem do data.frame

setDF(df)

Jeśli chcesz używać tylko data.frame i zachować czynniki, jest to trudniejsze, musisz popracować

levels(df$value)[levels(df$value)==""] <- NA

gdzie wartość to nazwa każdej kolumny. Musisz włożyć go w pętlę.

skan
źródło
2
Dlaczego miałbyś używać zewnętrznej biblioteki w tym przypadku użycia? Po co pętla, skoro można to rozwiązać za pomocą jednej linii? W jaki sposób Twoja odpowiedź wnosi wartość poza odpowiedzi już podane? Nie zamierzam być szorstki, chyba czegoś mi brakuje, stąd pytania.
sedot
2
Jest to znacznie szybsze w przypadku dużych zbiorów danych. Dodaje alternatywę, aby użytkownik mógł wybrać najlepszą dla siebie.
skan
0

Jeśli chcesz zastąpić wiele wartości w ramce danych, pomocne może być przejrzenie wszystkich kolumn w pętli.

Powiedz, że chcesz wymienić ""i 100:

na_codes <- c(100, "")
for (i in seq_along(df)) {
    df[[i]][df[[i]] %in% na_codes] <- NA
}
Olivier Ma
źródło