Удаление значений в DataFrame на основе условия R - PullRequest
0 голосов
/ 01 октября 2018

У меня есть фрейм данных из 4 столбцов (увеличенный для этого примера).Большинство столбцов имеют выбросы, которые значительно больше, чем другие значения во фрейме данных.Например: столбец (с максимальным значением 99) имеет выбросы с 96, 97, 98, 99. Эти выбросы по существу означают «нет ответа».Это явно сильно искажает данные, поэтому они должны быть удалены.Я хочу удалить выбросы, но каждая переменная имеет различное максимальное значение (и различный набор выбросов), а некоторые имеют десятичные дроби.

96, 97, 98, 99 должны быть удалены ТОЛЬКО из столбцов, имеющих тев качестве резервных значений.Таким образом, функция должна знать, какие столбцы имеют каждую конкретную классификацию резервных значений.Подробнее ниже.

Проблема в том, что я не хочу «удалять из всех столбцов» резервные значения, поскольку некоторые значения могут означать что-то другое в другом столбце.Например, удаление 996 в одном столбце может означать что-то значимое в другом столбце, например, почасовая заработная плата / неделя.

Это сложно, поскольку у некоторых есть десятичные дроби, например, отработанные часы / неделя.Например.37,5 часов, отработанных в неделю, будут иметь резервные значения 999,6, 999,7, 999,8, 999,9.Эта длина будет классифицирована как 5.1.

Мне нужно удалить эти резервные значения из фрейма данных, но они должны сначала соответствовать соответствующей длине резервного значения.Поскольку каждый столбец имеет различное значение резерва, имена столбцов кадра данных должны соответствовать определенному значению резерва.

df <- data.frame("children#" = c(1,5,0,2,10), 
    "annual income" = c(700000.00,50000.65,30000.45,1000000.59,9999999.96), 
    "hour wage"= c(25.65,9999999.99,50.23,1000.72,65.16), 
    "hours worked/week" = c(148.5,77.0,64.2,25.9,999.7))

Максимальная длина детей # равна 2 Максимальная длина годового дохода составляет 10,2 (всего 10)., 2 знака после запятой) Максимальная продолжительность часовой заработной платы составляет 10,2. Максимальная продолжительность отработанных часов / недели составляет 5,1 (всего 5, 1 десятичный знак)

ВСЕГДА БУДЕТ 4 РЕЗЕРВНЫХ ЗНАЧЕНИЯ
Если максимальная длина = 2, удалить резервзначения: 96,97,98,99
Если максимальная длина = 3, удалите резервные значения: 996, 997, 998, 999 ... и т. д. со сплошными числами

С десятичными знаками:
Если максимальная длина = 5,1, удалите резервные значения: 999,6, 999,7, 999,8, 999,9.
Если максимальная длина = 10,2, удалите резервные значения: 9999999,96, 9999999,97, 9999999,98, 9999999,99

Таким образом, я бы хотелвыяснить, как создать функцию, которая будет

  1. находить максимальные длины
  2. соединять соответствующие максимальные длины с правильными резервными значениями
  3. удалить резервные значенияиз фрейма данных на основе максимальной длины каждого столбца

Пока у меня есть максимальная длина каждого столбца с десятичными точками.

Мне просто нужна помощь с подключением к резервным значениям и удалением этих резервных значений из фрейма данных.

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

Пример кода: Для резервных значений я думал о создании отдельного фрейма данных и использовании его для удаления значений.Другие предложения приветствуются.

Find.Max.Length <- function(data){
# Check Max Length of each column
tmp <- data.frame(lapply(data, function(x) max(nchar(x, keepNA = F))))
tmp <- data.frame(t(tmp))
return(tmp)}
max.length <- Find.Max.Length(df)

Check.Decimal.Places <- function(x){
if((x %% 1) != 0){
nchar(strsplit(sub('0+$', '',as.character(x)), ".", fixed = TRUE)[[1]][[2]])
}else{
return(0)}
}

decimal <- data.frame(Check.Decimal.Places(df$random)) #<--- used to 
initialize the variable before the loop

for(i in seq_along(df)){
decimal[i] <- data.frame(Check.Decimal.Places(df[[i]]))}

decimal<- data.frame(t(decimal))
rownames(decimal) <- names(df)
length.df <- cbind(max.length, decimal)
names(length.df) <- c("Max Length", "Decimal Place")

length.df$NewVariableLength <- paste0(length.df$`Max Length`, sep= 
".",length.df$`Decimal Place`)

ПРИМЕЧАНИЕ. Имена строк фрейма данных length.df соответствуют исходным именам фрейма данных.Это может быть способ связать их вместе?

Вероятно, есть более быстрый способ сделать все это, все предложения приветствуются.

1 Ответ

0 голосов
/ 01 октября 2018

edit: Теперь я понимаю, что вы имеете в виду под "резервными значениями" - ответы из опроса, которые не должны учитываться (например, "Я не хочу отвечать на этот вопрос")

У вас есть, по сути, три простых метода без необходимости поиска «целочисленной длины» или другого чрезмерного инженерного анализа:

  1. Максимальные значения (т. Е. Удаление четырех самых высоких значений),
  2. Ручные пороги (т. Е. Удалить все значения выше X),
  3. Логика if-else (т. Е. Если ответ == X, удалить его).

Построение набора данных

Ваши данные не соответствуют вашим спецификациям («всегда 4 выброса»), поэтому я позволил себе расширить их.

df <- data.frame(
               "children" = c(1, 0, 96, 2, 10, 99, 98, 99),
               "annual_income" = c(700000.00, 50000.65, 30000.45, 1000000.59, 9999999.96, 9999999.97, 9999999.98, 9999999.99),
               "hour_wage"= c(25.65, 9999999.99, 50.23, 9999999.98, 9999999.99, 9999999.98, 1000.72, 65.16),
               "hours_worked_week" = c(148.5, 999.6, 77.0, 64.2, 999.9, 999.8, 25.9, 999.7)
               )

df
  children annual_income   hour_wage hours_worked_week
1        1     700000.00       25.65             148.5
2        0      50000.65  9999999.99             999.6
3       96      30000.45       50.23              77.0
4        2    1000000.59  9999999.98              64.2
5       10    9999999.96  9999999.99             999.9
6       99    9999999.97  9999999.98             999.8
7       98    9999999.98     1000.72              25.9
8       99    9999999.99       65.16             999.7

1.Подход к максимальным значениям (устарел после уточнения)

Загрузить библиотеки

library(dplyr)
library(magrittr)

Получить четыре выброса

children_out <- tail(sort(df$children), 4)

Заменить выбросы на NA

df[df$children %in% children_out,]
    %<>% mutate(children = NA)

Проверка набора данных

df
  children annual_income   hour_wage hours_worked_week
1        1     700000.00       25.65             148.5
2        0      50000.65  9999999.99             999.6
3       NA      30000.45       50.23              77.0
4        2    1000000.59  9999999.98              64.2
5       10    9999999.96  9999999.99             999.9
6       NA    9999999.97  9999999.98             999.8
7       NA    9999999.98     1000.72              25.9
8       NA    9999999.99       65.16             999.7

Предупреждение: этот подход будет работать , только если у вас всегда есть четыре выброса для каждого столбца .

2.Ручные пороги

Загрузка библиотек

library(dplyr)
library(magrittr)

Исключить существующий NA и заменить все, что 96 или выше, на NA

df[!is.na(df$children) & df$children >=96, ] %<>%
    mutate(children = NA)

Проверить набор данных

df
  children annual_income   hour_wage hours_worked_week
1        1     700000.00       25.65             148.5
2        0      50000.65  9999999.99             999.6
3       NA      30000.45       50.23              77.0
4        2    1000000.59  9999999.98              64.2
5       10    9999999.96  9999999.99             999.9
6       NA    9999999.97  9999999.98             999.8
7       NA    9999999.98     1000.72              25.9
8       NA    9999999.99       65.16             999.7

3.Логика if-else

Загрузка библиотек

library(dplyr)
library(magrittr)

Сохранение "зарезервированных ответов"

children_res <- c(96, 97, 98, 99)

Заменить все, что является зарезервированным ответом, на NA (исключая существующий NA, нездесь необходимо)

df[df$children %in% children_res, ] %<>%
    mutate(children = NA)

Проверить набор данных

df
  children annual_income   hour_wage hours_worked_week
1        1     700000.00       25.65             148.5
2        0      50000.65  9999999.99             999.6
3       NA      30000.45       50.23              77.0
4        2    1000000.59  9999999.98              64.2
5       10    9999999.96  9999999.99             999.9
6       NA    9999999.97  9999999.98             999.8
7       NA    9999999.98     1000.72              25.9
8       NA    9999999.99       65.16             999.7

4.edit: Комбинированный подход 1 & 3

Загрузка библиотек

library(dplyr)
library(magrittr)

Получить "зарезервированные ответы"

children_res <- tail(sort(unique(df$children)), 4)

Заменить все, что является зарезервированным ответом, с NA (исключая существующий NAздесь не требуется)

df[df$children %in% children_res, ] %<>%
    mutate(children = NA)

Предупреждение: этот подход будет работать только в том случае, если в каждом столбце присутствует ВСЕ зарезервированные ответы (например, 96, 97, 98 и 99).Это НЕ РАБОТАЕТ , если случайно никто не ответит "97".

...