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

Измените класс с факторного на числовой для многих столбцов во фрейме данных

Каков самый быстрый/лучший способ изменить большое количество столбцов на числовые из коэффициента?

Я использовал следующий код, но он, похоже, повторно заказал мои данные.

> head(stats[,1:2])
  rk                 team
1  1 Washington Capitals*
2  2     San Jose Sharks*
3  3  Chicago Blackhawks*
4  4     Phoenix Coyotes*
5  5   New Jersey Devils*
6  6   Vancouver Canucks*

for(i in c(1,3:ncol(stats))) {
    stats[,i] <- as.numeric(stats[,i])
}

> head(stats[,1:2])
  rk                 team
1  2 Washington Capitals*
2 13     San Jose Sharks*
3 24  Chicago Blackhawks*
4 26     Phoenix Coyotes*
5 27   New Jersey Devils*
6 28   Vancouver Canucks*

Каков наилучший способ, не называя каждого столбца, как в:

df$colname <- as.numeric(ds$colname)
4b9b3361

Ответ 1

В ответ на ответ Рамната поведение, которое вы испытываете, состоит в том, что из-за as.numeric(x) возврата внутреннего числового представления коэффициента x на уровне R. Если вы хотите сохранить числа, которые являются уровнями фактора (а не их внутренним представлением), вам нужно сначала преобразовать символ через as.character() в соответствии с примером Рамната.

Ваш цикл for столь же разумен, как и вызов apply, и может быть немного более читабельным относительно того, каково намерение кода. Просто измените эту строку:

stats[,i] <- as.numeric(stats[,i])

читать

stats[,i] <- as.numeric(as.character(stats[,i]))

Это FAQ 7.10 в FAQ FAQ.

НТН

Ответ 2

Вы должны быть осторожны при изменении факторов на числовые. Вот строка кода, которая изменила бы набор столбцов от коэффициента к числовому. Я предполагаю, что столбцы, которые нужно изменить на числовые, равны 1, 3, 4 и 5 соответственно. Вы можете изменить его соответствующим образом.

cols = c(1, 3, 4, 5);    
df[,cols] = apply(df[,cols], 2, function(x) as.numeric(as.character(x)));

Ответ 3

Это может быть сделано в одной строке, нет необходимости в цикле, будь то цикл for или применение. Вместо этого используйте unlist():

# testdata
Df <- data.frame(
  x = as.factor(sample(1:5,30,r=TRUE)),
  y = as.factor(sample(1:5,30,r=TRUE)),
  z = as.factor(sample(1:5,30,r=TRUE)),
  w = as.factor(sample(1:5,30,r=TRUE))
)
##

Df[,c("y","w")] <- as.numeric(as.character(unlist(Df[,c("y","w")])))

str(Df)

Изменение: для вашего кода это становится:

id <- c(1,3:ncol(stats))) 
stats[,id] <- as.numeric(as.character(unlist(stats[,id])))

Очевидно, что если у вас есть фрейм данных из одного столбца, и вы не хотите, чтобы автоматическое уменьшение размера R преобразовывало его в вектор, вам придется добавить аргумент drop=FALSE.

Ответ 4

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

library(magrittr)
cols = c(1, 3, 4, 5)
df[,cols] %<>% lapply(function(x) as.numeric(as.character(x)))

Оператор %<>% направляет и переназначает, что очень полезно для упрощения очистки и преобразования данных. Теперь функцию применения списка гораздо проще читать, указав только функцию, которую вы хотите применить.

Ответ 5

Я думаю, что ucfagls нашел, почему ваш цикл не работает.

Если вы все еще не хотите использовать цикл, то это решение с lapply:

factorToNumeric <- function(f) as.numeric(levels(f))[as.integer(f)] 
cols <- c(1, 3:ncol(stats))
stats[cols] <- lapply(stats[cols], factorToNumeric)

Изменить. Я нашел более простое решение. Кажется, что as.matrix преобразуется в символ. Так

stats[cols] <- as.numeric(as.matrix(stats[cols]))

должен делать то, что вы хотите.

Ответ 6

lapply в значительной степени предназначен для этого

unfactorize<-c("colA","colB")
df[,unfactorize]<-lapply(unfactorize, function(x) as.numeric(as.character(df[,x])))

Ответ 7

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

df <- data.frame(x = 1:10,
                 y = rep(1:2, 5),
                 k = rnorm(10, 5,2),
                 z = rep(c(2010, 2012, 2011, 2010, 1999), 2),
                 j = c(rep(c("a", "b", "c"), 3), "d"))

convert.magic <- function(obj, type){
  FUN1 <- switch(type,
                 character = as.character,
                 numeric = as.numeric,
                 factor = as.factor)
  out <- lapply(obj, FUN1)
  as.data.frame(out)
}

str(df)
str(convert.magic(df, "character"))
str(convert.magic(df, "factor"))
df[, c("x", "y")] <- convert.magic(df[, c("x", "y")], "factor")

Ответ 8

Я хотел бы указать, что если у вас есть NA в любом столбце, просто использование индексов не будет работать. Если в коэффициенте есть NA, вы должны использовать приложение script, предоставленное Ramnath.

например.

Df <- data.frame(
  x = c(NA,as.factor(sample(1:5,30,r=T))),
  y = c(NA,as.factor(sample(1:5,30,r=T))),
  z = c(NA,as.factor(sample(1:5,30,r=T))),
  w = c(NA,as.factor(sample(1:5,30,r=T)))
)

Df[,c(1:4)] <- as.numeric(as.character(Df[,c(1:4)]))

Возвращает следующее:

Warning message:
NAs introduced by coercion 

    > head(Df)
       x  y  z  w
    1 NA NA NA NA
    2 NA NA NA NA
    3 NA NA NA NA
    4 NA NA NA NA
    5 NA NA NA NA
    6 NA NA NA NA

Но:

Df[,c(1:4)]= apply(Df[,c(1:4)], 2, function(x) as.numeric(as.character(x)))

Возврат:

> head(Df)
   x  y  z  w
1 NA NA NA NA
2  2  3  4  1
3  1  5  3  4
4  2  3  4  1
5  5  3  5  5
6  4  2  4  4

Ответ 9

Вы можете использовать unfactor() из пакета CRAN "varhandle":

library("varhandle")

my_iris <- data.frame(Sepal.Length = factor(iris$Sepal.Length),
                      sample_id = factor(1:nrow(iris)))

my_iris <- unfactor(my_iris)

Ответ 10

Мне нравится этот код, потому что он довольно удобен:

  data[] <- lapply(data, function(x) type.convert(as.character(x), as.is = TRUE)) #change all vars to their best fitting data type

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

Ответ 11

Вот несколько вариантов dplyr:

# by column type:
df %>% 
  mutate_if(is.factor, ~as.numeric(as.character(.)))

# by specific columns:
df %>% 
  mutate_at(vars(x, y, z), ~as.numeric(as.character(.))) 

# all columns:
df %>% 
  mutate_all(~as.numeric(as.character(.))) 

Ответ 12

У меня были проблемы с преобразованием всех столбцов в числовые с вызовом apply():

apply(data, 2, as.numeric)

Проблема заключается в том, что некоторые из строк имеют в них запятую - например, "1,024,63" вместо "1024,63" - и R не нравится этот способ форматирования чисел. Поэтому я удалил их, а затем побежал as.numeric():

data = as.data.frame(apply(data, 2, function(x) {
  y = str_replace_all(x, ",", "") #remove commas
  return(as.numeric(y)) #then convert
}))

Обратите внимание, что для этого требуется, чтобы загружался пакет stringr.

Ответ 13

Что сработало для меня. Функция apply() пытается принудить df к матрице и возвращает NA.

numeric.df <- as.data.frame(sapply(df, 2, as.numeric))

Ответ 14

Основываясь на ответе @SDahm, это было "оптимальное" решение для моего tibble:

data %<>% lapply(type.convert) %>% as.data.table()

Это требует dplyr и magrittr.

Ответ 15

Я перепробовал несколько подобных проблем и продолжал получать АН. Base R имеет некоторые действительно раздражающие способы принуждения, которые обычно исправляются в пакетах Tidyverse. Раньше я избегал их, потому что не хотел создавать зависимости, но они делают жизнь намного проще, и теперь я даже не пытаюсь найти решение Base R большую часть времени.

Вот решение Tidyverse, которое предельно просто и элегантно:

library(purrr)

mydf <- data.frame(
  x1 = factor(c(3, 5, 4, 2, 1)),
  x2 = factor(c("A", "C", "B", "D", "E")),
  x3 = c(10, 8, 6, 4, 2))

map_df(mydf, as.numeric)

Ответ 16

df$colname <- as.numeric(df$colname)

Я попробовал этот способ для изменения одного типа столбца, и я думаю, что это лучше, чем многие другие версии, если вы не собираетесь менять все типы столбцов

df$colname <- as.character(df$colname)

для наоборот.