Заменить все конкретные значения во фрейме данных


90

Имея фрейм данных, как мне заменить все конкретные значения во всех строках и столбцах. Скажем, например, я хочу заменить все пустые записи на NA's (без ввода позиций):

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

    A   B
1      12
2  xyz    
3  jkl 100

Ожидаемый результат:

    A   B
1  NA   12
2  xyz  NA  
3  jkl  100

Ответы:


139

Как это:

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

14
есть ли способ сделать это эффективно для более чем одного значения !?
PikkuKatja

28
Это не работает для факторов, df[df=="xyz"]<-"abc"приведет к ошибке с «недопустимым уровнем фактора». Есть ли более общее решение?
glallen 02

1
у меня не работает. Я пробовал это: dfSmallDiscreteCustomSalary [dfSmallDiscreteCustomSalary $ salary == "<= 50K"] <- "49K". По-прежнему для уникального (dfSmallDiscreteCustomSalary $ salary) я получаю: [1]> 50K <= 50K
Codious-JR

3
glallen ... если вы пытаетесь изменить столбец факторов с новым значением, которое уже является фактором, вероятно, есть более умные способы, чем то, что я собираюсь предложить, но вы можете df $ factorcolumn <- as.character ( df $ factorcolumn), затем внесите изменения и закончите, снова превратив его обратно в фактор ... df $ factorcolumn <- as.factor (df $ factorcolumn); он будет завершен с вашим новым уровнем и желаемой стоимостью.
Джошуа Эрик Тюркотт

Выяснил: df.na.replace (df.columns, Map ("" -> "NA")). Show. Интересно, что я не могу заменить значение null на значение. Я получаю: java.lang.IllegalArgumentException: неподдерживаемый тип значения java.lang.String (null). at org.apache.spark.sql.DataFrameNaFunctions.org $ apache $ spark $ sql $ DataFrameNaFunctions $$ convertToDouble (DataFrameNaFunctions.scala: 434)
ширам,

34

Поскольку PikkuKatja и glallen попросили более общее решение, и я пока не могу комментировать, я напишу ответ. Вы можете комбинировать утверждения, как в:

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

Для факторов код zxzak уже дает факторы:

> 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

Если возникнут проблемы, я предлагаю временно отказаться от факторов.

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

18

Вот пара dplyrвариантов:

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'))

Как бы вы применили решение для всех столбцов для замены нескольких строк на NA во всем наборе данных?
Tea Tree

4

Мы можем использовать data.table, чтобы получить его быстро. Сначала создайте df без факторов,

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

Теперь вы можете использовать

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

и вы можете преобразовать его обратно в data.frame

setDF(df)

Если вы хотите использовать только data.frame и сохранить факторы, которые сложнее, вам нужно работать с

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

где значение - это имя каждого столбца. Вам нужно вставить его в петлю.


2
Зачем вам использовать внешнюю библиотеку для этого варианта использования? Зачем нужен цикл, если это можно решить одной строкой? Как ваш ответ повышает ценность уже имеющихся ответов? Я не собираюсь быть резким, я думаю, что что-то упускаю, отсюда и вопросы.
sedot

2
Это намного быстрее для больших наборов данных. Он добавляет альтернативу, чтобы пользователь мог выбрать лучшее для себя.
skan

0

Если вы хотите заменить несколько значений во фрейме данных, может помочь цикл по всем столбцам.

Допустим, вы хотите заменить ""и 100:

na_codes <- c(100, "")
for (i in seq_along(df)) {
    df[[i]][df[[i]] %in% na_codes] <- NA
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.