Verander de klasse van factor in numeriek van veel kolommen in een dataframe

Wat is de snelste/beste manier om een ​​groot aantal kolommen van factor naar numeriek te veranderen?

Ik heb de volgende code gebruikt, maar het lijkt erop dat mijn gegevens opnieuw zijn gerangschikt.

> 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*

Wat is de beste manier, behalve elke kolom een ​​naam te geven zoals in:

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

Antwoord 1, autoriteit 100%

Je moet voorzichtig zijn bij het wijzigen van factoren in numeriek. Hier is een regel code die een reeks kolommen zou veranderen van factor in numeriek. Ik neem hier aan dat de kolommen die moeten worden gewijzigd in numeriek respectievelijk 1, 3, 4 en 5 zijn. Je zou het dienovereenkomstig kunnen wijzigen

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

Antwoord 2, autoriteit 77%

Vervolgens Ramnath’s antwoord, is het gedrag dat u ervaart het gevolg van het feit dat as.numeric(x)de interne, numerieke representatie van de factor xaan de R retourneert niveau. Als je de getallen wilt behouden die de niveaus van de factor zijn (in plaats van hun interne representatie), moet je eerst converteren naar teken via as.character()volgens het voorbeeld van Ramnath.

Je for-lus is net zo redelijk als een apply-aanroep en is misschien iets beter leesbaar wat de bedoeling van de code is. Verander gewoon deze regel:

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

om te lezen

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

Dit is FAQ 7.10in de R FAQ.

HTH


Antwoord 3, autoriteit 54%

Dit kan in één regel worden gedaan, er is geen lus nodig, of het nu een for-lus of een toepassing is. Gebruik in plaats daarvan 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)

Bewerken: voor uw code wordt dit:

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

Als u een dataframe met één kolom heeft en u wilt niet dat de automatische dimensiereductie van R deze omzet in een vector, moet u uiteraard de drop=FALSEtoevoegen argument.


Antwoord 4, autoriteit 43%

Ik weet dat deze vraag al lang is opgelost, maar ik had onlangs een soortgelijk probleem en ik denk dat ik een iets elegantere en functionelere oplossing heb gevonden, hoewel het magrittr-pakket vereist is.

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

De operator %<>%leidt enopnieuw toe, wat erg handig is om het opschonen en transformeren van gegevens eenvoudig te houden. Nu is de lijsttoepassingsfunctie veel gemakkelijker te lezen, door alleen de functie op te geven die u wilt toepassen.


Antwoord 5, autoriteit 20%

Hier zijn enkele dplyropties:

# 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(.))) 

Antwoord 6, autoriteit 8%

Ik denk dat ucfagls heeft gevonden waaromuw loop niet werkt.

Als je nog steeds geen lus wilt gebruiken, is hier een oplossing met lapply:

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

Bewerken. Ik heb een eenvoudigere oplossing gevonden. Het lijkt erop dat as.matrixconverteert naar karakter. Dus

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

moet doen wat je wilt.


Antwoord 7, autoriteit 7%

Lapply is hier min of meer voor ontworpen

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

Antwoord 8, autoriteit 3%

Ik vond deze functie in een paar andere dubbele threads en vond het een elegante en algemene manier om dit probleem op te lossen. Deze thread verschijnt als eerste bij de meeste zoekopdrachten over dit onderwerp, dus ik deel het hier om mensen wat tijd te besparen. Ik neem hier geen eer voor, dus bekijk de originele berichten hieren hiervoor details.

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

Antwoord 9

Ik wil erop wijzen dat als je NA’s in een kolom hebt, het gebruik van subscripts niet werkt. Als er NA’s in de factor zijn, moet u het toepassingsscript van Ramnath gebruiken.

Bijvoorbeeld

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

Retourneert het volgende:

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

Maar:

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

Retouren:

> 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

Antwoord 10

u kunt de functie unfactor()gebruiken uit het pakket “varhandle” van CRAN:

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

11

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

Ik probeerde op deze manier voor het veranderen van het type één kolom en ik denk dat het beter dan vele andere versies, als je niet van plan om alle soorten kolom te veranderen

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

voor de vice versa.

Other episodes