Вопрос: Преобразование символа в числовое без принуждения NA в R


Я работаю в R и имею DataFrame, dd_2006, с числовыми векторами. Когда я впервые импортировал данные, мне нужно было удалить $, десятичные точки и некоторые пробелы из 3 моих переменных: SumOfCost, SumOfCases и SumOfUnits. Для этого я использовал str_replace_all, Однако, как только я использовал str_replace_all, векторы были преобразованы в символы. Поэтому я использовал as.numeric (var) для преобразования векторов в числовые, но были введены NA, хотя, когда я запускал код ниже BEFORE, я запускал as.numeric code, в векторах не было NA.

sum(is.na(dd_2006$SumOfCost))
[1] 0
sum(is.na(dd_2006$SumOfCases))
[1] 0
sum(is.na(dd_2006$SumOfUnits))
[1] 0

Вот мой код после импорта, начиная с удаления $ из вектора. в str(dd_2006) вывода, я удалил некоторые из переменных ради пространства, поэтому столбец #s в str_replace_all код ниже не соответствуют выводимому здесь выводам (но они делают в исходном коде):

library("stringr")
dd_2006$SumOfCost <- str_sub(dd_2006$SumOfCost, 2, ) #2=the first # after the $

#Removes decimal pt, zero's after, and commas
dd_2006[ ,9] <- str_replace_all(dd_2006[ ,9], ".00", "")
dd_2006[,9] <- str_replace_all(dd_2006[,9], ",", "")

dd_2006[ ,10] <- str_replace_all(dd_2006[ ,10], ".00", "")
dd_2006[ ,10] <- str_replace_all(dd_2006[,10], ",", "")

dd_2006[ ,11] <- str_replace_all(dd_2006[ ,11], ".00", "")
dd_2006[,11] <- str_replace_all(dd_2006[,11], ",", "")

str(dd_2006)
'data.frame':   12604 obs. of  14 variables:
 $ CMHSP                     : Factor w/ 46 levels "Allegan","AuSable Valley",..: 1 1 1
 $ FY                        : Factor w/ 1 level "2006": 1 1 1 1 1 1 1 1 1 1 ...
 $ Population                : Factor w/ 1 level "DD": 1 1 1 1 1 1 1 1 1 1 ...
 $ SumOfCases                : chr  "0" "1" "0" "0" ...
 $ SumOfUnits                : chr  "0" "365" "0" "0" ...
 $ SumOfCost                 : chr  "0" "96416" "0" "0" ...

Я нашел ответ на аналогичный вопрос на мой Вот , используя следующий код:

# create dummy data.frame
d <- data.frame(char = letters[1:5], 
                fake_char = as.character(1:5), 
                fac = factor(1:5), 
                char_fac = factor(letters[1:5]), 
                num = 1:5, stringsAsFactors = FALSE)

Давайте взглянем на data.frame

> d
  char fake_char fac char_fac num
1    a         1   1        a   1
2    b         2   2        b   2
3    c         3   3        c   3
4    d         4   4        d   4
5    e         5   5        e   5

и давайте убежим:

> sapply(d, mode)
       char   fake_char         fac    char_fac         num 
"character" "character"   "numeric"   "numeric"   "numeric" 
> sapply(d, class)
       char   fake_char         fac    char_fac         num 
"character" "character"    "factor"    "factor"   "integer" 

Теперь вы, вероятно, спрашиваете себя: «Где аномалия?» Ну, я столкнулся с довольно своеобразными вещами в R, и это не самая неприятная вещь, но это может вас смутить, особенно если вы прочитаете это, прежде чем вскарабкаться в постель.

Вот так: первые два столбца являются символами. Я сознательно назвал второй fake_char. Определите сходство этой символьной переменной с тем, что создал Дирк в своем ответе. Это фактически числовой вектор, преобразованный в характер. Третий и четвертый столбцы являются факторами, а последний - «чисто» числовыми.

Если вы используете функцию преобразования, вы можете преобразовать fake_char в числовую, но не переменную char.

> transform(d, char = as.numeric(char))
  char fake_char fac char_fac num
1   NA         1   1        a   1
2   NA         2   2        b   2
3   NA         3   3        c   3
4   NA         4   4        d   4
5   NA         5   5        e   5
Warning message:
In eval(expr, envir, enclos) : NAs introduced by coercion
but if you do same thing on fake_char and char_fac, you'll be lucky, and get away with no NA's:

transform (d, fake_char = as.numeric (fake_char),                  char_fac = as.numeric (char_fac))

  char fake_char fac char_fac num
1    a         1   1        1   1
2    b         2   2        2   2
3    c         3   3        3   3
4    d         4   4        4   4
5    e         5   5        5   5

Поэтому я попробовал приведенный выше код в своем сценарии, но все же придумал NA (без предупреждения о принуждении).

#changing sumofcases, cost, and units to numeric
dd_2006_1 <- transform(dd_2006, SumOfCases = as.numeric(SumOfCases), SumOfUnits = as.numeric(SumOfUnits), SumOfCost = as.numeric(SumOfCost))

> sum(is.na(dd_2006_1$SumOfCost))
[1] 12
> sum(is.na(dd_2006_1$SumOfCases))
[1] 7
> sum(is.na(dd_2006_1$SumOfUnits))
[1] 11

Я также использовал table(dd_2006$SumOfCases) и т. д., чтобы посмотреть на наблюдения, чтобы увидеть, есть ли какие-либо символы, которые я пропустил в наблюдениях, но их не было. Любые мысли о том, почему НС появляются, и как избавиться от них?


6


источник


Ответы:


Как заметил Анандо, проблема заключается в ваших данных, и мы не можем вам очень помочь, без воспроизводимого примера. Тем не менее, вот фрагмент кода, который поможет вам зафиксировать записи в ваших данных, которые вызывают проблемы:

test = as.character(c(1,2,3,4,'M'))
v = as.numeric(test) # NAs intorduced by coercion
ix.na = is.na(v)
which(ix.na) # row index of our problem = 5
test[ix.na]  # shows the problematic record, "M"

Вместо того, чтобы угадывать, почему вводятся NA, вытащите записи, которые вызывают проблему, и обращаются к ним напрямую / индивидуально до тех пор, пока NA не исчезнут.

ОБНОВЛЕНИЕ: Похоже, проблема заключается в вашем обращении к str_replace_all, Я не знаю stringr библиотеки, но я думаю, что вы можете сделать то же самое с gsub как это:

v2 = c("1.00","2.00","3.00")
gsub("\\.00", "", v2)

[1] "1" "2" "3"

Я не совсем уверен, что это делает:

sum(as.numeric(v2)!=as.numeric(gsub("\\.00", "", v2))) # Illustrate that vectors are equivalent.

[1] 0

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


13



Если вы хотите преобразовать символ в числовой, а затем сначала преобразуйте его в коэффициент (используя as.factor) и сохраните / перезапишите существующую переменную. Затем преобразуйте эту переменную в числовое значение (используя as.numeric). Вы бы не создали NAs таким образом и сможете преобразовать набор данных, который у вас есть, в числовой.


4