In het R-gegevensframe dat hieronder is gecodeerd, wil ik alle keren vervangen dat B
verschijnt met B
.
junk <- data.frame(x <- rep(LETTERS[1:4], 3), y <- letters[1:12])
colnames(junk) <- c("nm", "val")
dit biedt:
nm val
1 A a
2 B b
3 C c
4 D d
5 A e
6 B f
7 C g
8 D h
9 A i
10 B j
11 C k
12 D l
Mijn eerste poging was om for
en if
statements te gebruiken zoals:
for(i in junk$nm) if(i %in% "B") junk$nm <- "b"
maar zoals je zeker kunt zien, vervangt dit ALLE waarden van junk$nm
door B
. Ik begrijp waarom dit dit doet, maar ik krijg het niet voor elkaar om alleen die gevallen van junk$nm te vervangen waar de oorspronkelijke waarde B
was.
OPMERKING: ik heb het probleem met gsub
kunnen oplossen, maar in het belang van het leren van R zou ik toch graag willen weten hoe ik mijn oorspronkelijke aanpak kan laten werken (als het mogelijk is)
Antwoord 1, autoriteit 100%
Gemakkelijker om nm naar tekens te converteren en vervolgens de wijziging aan te brengen:
junk$nm <- as.character(junk$nm)
junk$nm[junk$nm == "B"] <- "b"
EDIT: En als je inderdaad nm als factoren wilt behouden, voeg dan dit op het einde toe:
junk$nm <- as.factor(junk$nm)
Antwoord 2, autoriteit 20%
een andere handige manier om waarden te vervangen
library(plyr)
junk$nm <- revalue(junk$nm, c("B"="b"))
Antwoord 3, autoriteit 12%
Kort antwoord is:
junk$nm[junk$nm %in% "B"] <- "b"
Bekijk Indexvectoren in R Inleiding(als je het nog niet leest).
BEWERKEN. Zoals opgemerkt in opmerkingen, werkt deze oplossing voor karaktervectoren, dus faal op uw gegevens.
De beste manier is om van niveau te veranderen:
levels(junk$nm)[levels(junk$nm)=="B"] <- "b"
Antwoord 4, autoriteit 9%
Omdat de gegevens die u laat zien factoren zijn, wordt de zaak een beetje ingewikkelder. @diliop’s Answer benadert het probleem door nm
om te zetten in een karaktervariabele. Om terug te keren naar de oorspronkelijke factoren is een volgende stap vereist.
Een alternatief is om de niveaus van de aanwezige factor te manipuleren.
> lev <- with(junk, levels(nm))
> lev[lev == "B"] <- "b"
> junk2 <- within(junk, levels(nm) <- lev)
> junk2
nm val
1 A a
2 b b
3 C c
4 D d
5 A e
6 b f
7 C g
8 D h
9 A i
10 b j
11 C k
12 D l
Dat is vrij eenvoudig en ik vergeet vaak dat er een vervangingsfunctie is voor levels()
.
Bewerken:Zoals @Seth in de opmerkingen opmerkt, kan dit in een one-liner, zonder verlies van duidelijkheid:
within(junk, levels(nm)[levels(nm) == "B"] <- "b")
Antwoord 5, autoriteit 5%
De gemakkelijkste manier om dit in één opdracht te doen, is door de opdracht which
te gebruiken en ook de factoren niet in tekens te veranderen door dit te doen:
junk$nm[which(junk$nm=="B")]<-"b"
Antwoord 6, autoriteit 2%
Je hebt een factorvariabele gemaakt in nm
, dus je moet dit ofwel vermijden, ofwel een extra niveau toevoegen aan de factorattributen. Vermijd ook het gebruik van <-
in de argumenten voor data.frame()
Optie 1:
junk <- data.frame(x = rep(LETTERS[1:4], 3), y =letters[1:12], stringsAsFactors=FALSE)
junk$nm[junk$nm == "B"] <- "b"
Optie 2:
levels(junk$nm) <- c(levels(junk$nm), "b")
junk$nm[junk$nm == "B"] <- "b"
junk
Antwoord 7
Als u met karaktervariabelen werkt (merk op dat stringsAsFactors
hier onwaar is), kunt u vervangen:
junk <- data.frame(x <- rep(LETTERS[1:4], 3), y <- letters[1:12], stringsAsFactors = FALSE)
colnames(junk) <- c("nm", "val")
junk$nm <- replace(junk$nm, junk$nm == "B", "b")
junk
# nm val
# 1 A a
# 2 b b
# 3 C c
# 4 D d
# ...
Antwoord 8
stata.replace<-function(data,replacevar,replacevalue,ifs) {
ifs=parse(text=ifs)
yy=as.numeric(eval(ifs,data,parent.frame()))
x=sum(yy)
data=cbind(data,yy)
data[yy==1,replacevar]=replacevalue
message=noquote(paste0(x, " replacement are made"))
print(message)
return(data[,1:(ncol(data)-1)])
}
Roep deze functie aan met de onderstaande regel.
d=stata.replace(d,"under20",1,"age<20")
Antwoord 9
Je kunt ook ifelse
gebruiken, wat heel eenvoudig te begrijpen is
junk$val <- ifelse(junk$nm == "B", "b", junk$val)
Als je het nog steeds wilt doen via for loop
de juiste manier om het te doen
for(i in 1:nrow(junk)){
if(junk[i, "nm"] == "B"){
junk[i, "val"] <- "b"
}
}
junk
> junk
nm val
1 A a
2 B b
3 C c
4 D d
5 A e
6 B b
7 C g
8 D h
9 A i
10 B b
11 C k
12 D l
Antwoord 10
Ik heb hetzelfde probleem, je kunt ook hetzelfde doen voor elke kolom,
fix_junk <- function(x){
#x <- as.character(x)
x[x == "B"] <- "b"
x
}
junk[] <- lapply(junk, fix_junk); junk # junk[] to get a data frame rather than a list
junk[1:3] <- lapply(junk[1:3], fix_junk); junk