Zastąp wartość w ramce danych na podstawie instrukcji warunkowej ("if")
W ramce danych r zakodowanej poniżej, chciałbym zastąpić wszystkie czasy, które B
pojawia się z b
.
junk <- data.frame(x <- rep(LETTERS[1:4], 3), y <- letters[1:12])
colnames(junk) <- c("nm", "val")
To zapewnia:
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
Moją początkową próbą było użycie for
i if
wypowiedzi w ten sposób:
for(i in junk$nm) if(i %in% "B") junk$nm <- "b"
Ale jak zapewne widzisz, zastępuje to wszystkie wartości junk$nm
na b
. Widzę, dlaczego tak się dzieje, ale nie mogę go zastąpić tylko tymi przypadkami śmieci$nm, gdzie oryginalna wartość była B
.
Uwaga: udało mi się rozwiązać problem z gsub
ale w interesie nauki r nadal chciałbym wiedzieć, jak uzyskać moje oryginalne podejście do pracy (jeśli jest to możliwe)
8 answers
Łatwiej przekonwertować nm na znaki, a następnie dokonać zmiany:
junk$nm <- as.character(junk$nm)
junk$nm[junk$nm == "B"] <- "b"
EDIT: a jeśli rzeczywiście musisz utrzymać nm jako czynniki, dodaj to na końcu:
junk$nm <- as.factor(junk$nm)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-28 20:50:01
Inny użyteczny sposób zastępowania wartości
library(plyr)
junk$nm <- revalue(junk$nm, c("B"="b"))
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-11-11 22:10:29
Krótka odpowiedź brzmi:
junk$nm[junk$nm %in% "B"] <- "b"
Spójrz na wektory indeksowe we wstępie R (Jeśli jeszcze go nie przeczytałeś).
EDIT. Jak zauważono w komentarzach To rozwiązanie działa dla wektorów znaków, więc nie na danych.
Dla czynnika najlepszym sposobem jest zmiana poziomu:
levels(junk$nm)[levels(junk$nm)=="B"] <- "b"
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-28 20:37:16
Ponieważ dane, które pokazujesz, są czynnikami, to trochę komplikuje sprawy. odpowiedź @diliop podchodzi do problemu poprzez konwersję do nm
na zmienną znakową. Aby wrócić do pierwotnych czynników, wymagany jest kolejny krok.
Alternatywą jest manipulowanie poziomami czynnika w miejscu.
> 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
Jest to dość proste i często zapominam, że istnieje funkcja zastępcza dla levels()
.
Edit: Jak zauważył @Seth w komentarzach, można to zrobić w jednowarstwowe, bez utraty przejrzystości:
within(junk, levels(nm)[levels(nm) == "B"] <- "b")
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-29 08:39:08
Najprostszym sposobem, aby to zrobić w jednym poleceniu jest użycie polecenia which
, a także nie trzeba zmieniać czynników na charakter, wykonując to:
junk$nm[which(junk$nm=="B")]<-"b"
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-07 13:31:27
Stworzyłeś zmienną czynnika w nm
, więc albo musisz tego uniknąć, albo dodać dodatkowy poziom do atrybutów czynnika. Należy również unikać używania <-
w argumentach do danych.frame ()
Wariant 1:
junk <- data.frame(x = rep(LETTERS[1:4], 3), y =letters[1:12], stringsAsFactors=FALSE)
junk$nm[junk$nm == "B"] <- "b"
Opcja 2:
levels(junk$nm) <- c(levels(junk$nm), "b")
junk$nm[junk$nm == "B"] <- "b"
junk
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-28 20:18:39
Jeśli pracujesz ze zmiennymi znakowymi (zauważ, że stringsAsFactors
jest tutaj false) możesz użyć replace:
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
# ...
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-20 15:28:44
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)])
}
Wywołanie tej funkcji za pomocą poniższej linii.
d=stata.replace(d,"under20",1,"age<20")
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-04-08 07:10:03