Substitua todos os valores particulares em um quadro de dados

96

Tendo um quadro de dados, como faço para substituir todos os valores particulares ao longo de todas as linhas e colunas. Digamos, por exemplo, que eu queira substituir todos os registros vazios por NA's (sem digitar as posições):

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

    A   B
1      12
2  xyz    
3  jkl 100

Resultado esperado:

    A   B
1  NA   12
2  xyz  NA  
3  jkl  100
zxzak
fonte

Respostas:

145

Como isso:

> df[df==""]<-NA
> df
     A    B
1 <NA>   12
2  xyz <NA>
3  jkl  100
srip
fonte
14
existe uma maneira de fazer isso de forma eficiente por mais de 1 valor !?
PikkuKatja
28
Isso não funciona para fatores, df[df=="xyz"]<-"abc"apresentará erro com "nível de fator inválido". Existe uma solução mais geral?
glallen,
1
não está funcionando para mim. Eu tentei isso: dfSmallDiscreteCustomSalary [dfSmallDiscreteCustomSalary $ salary == "<= 50K"] <- "49K". Ainda para exclusivo (dfSmallDiscreteCustomSalary $ salary), eu obtenho: [1]> 50K <= 50K
Codious-JR
3
glallen ... se você está tentando modificar uma coluna de fator com um novo valor que já é um fator, provavelmente existem maneiras mais inteligentes do que o que estou prestes a sugerir, mas você poderia df $ factorcolumn <- as.character ( df $ factorcolumn), então faça sua modificação e termine transformando-o novamente em um fator ... df $ factorcolumn <- as.factor (df $ factorcolumn); estará completo com seu novo nível e valor desejado.
Joshua Eric Turcotte,
Encontrado: df.na.replace (df.columns, Map ("" -> "NA")). Show. Curiosamente, não consigo substituir por null como valor. Estou recebendo: java.lang.IllegalArgumentException: Tipo de valor não suportado java.lang.String (null). em org.apache.spark.sql.DataFrameNaFunctions.org $ apache $ spark $ sql $ DataFrameNaFunctions $$ convertToDouble (DataFrameNaFunctions.scala: 434)
sriram
35

Como PikkuKatja e glallen pediram uma solução mais geral e ainda não posso comentar, escreverei uma resposta. Você pode combinar afirmações como em:

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

Para fatores, o código do zxzak já produz fatores:

> 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

Se estiver com problemas, sugiro abandonar temporariamente os fatores.

df[] <- lapply(df, as.character)
sedot
fonte
20

Aqui estão algumas dplyropções:

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
fonte
Como você usaria a solução de todas as colunas para substituir várias strings por NAs em todo o conjunto de dados?
Tea Tree de
4

Podemos usar data.table para obtê-lo rapidamente. Primeiro crie df sem fatores,

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

Agora você pode usar

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

e você pode convertê-lo de volta para um data.frame

setDF(df)

Se você deseja apenas usar data.frame e manter fatores, é mais difícil, você precisa trabalhar com

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

onde valor é o nome de cada coluna. Você precisa inseri-lo em um loop.

Skan
fonte
2
Por que você usaria uma biblioteca externa para este caso de uso? Por que um loop se isso pode ser resolvido com uma linha? Como sua resposta agrega valor além das respostas já apresentadas? Não pretendo ser duro, acho que estou faltando alguma coisa, daí as perguntas.
sedot
2
É muito mais rápido para grandes conjuntos de dados. Adiciona uma alternativa para que o usuário escolha o melhor para ele.
skan de
0

Se você deseja substituir vários valores em um quadro de dados, o loop em todas as colunas pode ajudar.

Digamos que você queira substituir ""e 100:

na_codes <- c(100, "")
for (i in seq_along(df)) {
    df[[i]][df[[i]] %in% na_codes] <- NA
}
Olivier Ma
fonte