programing

조건부('if') 문을 기준으로 데이터 프레임의 값 바꾸기

testmans 2023. 7. 19. 21:13
반응형

조건부('if') 문을 기준으로 데이터 프레임의 값 바꾸기

아래에 대해 코드화된 R 데이터 프레임에서, 나는 모든 시간을 대체하고 싶습니다.B와 함께 표시됩니다.b.

junk <- data.frame(x <- rep(LETTERS[1:4], 3), y <- letters[1:12])
colnames(junk) <- c("nm", "val")

이 기능은 다음과 같습니다.

   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

제가 처음 시도한 것은for그리고.if다음과 같은 문장:

for(i in junk$nm) if(i %in% "B") junk$nm <- "b"

하지만 보시다시피, 이것은 모든 가치를 대체합니다.junk$nm와 함께b나는 이것이 왜 이것을 하는지 알 수 있지만 나는 그것이 원래 값이었던 정크 $nm의 경우만 대체하도록 할 수 없는 것 같습니다.B.

참고: 문제를 해결할 수 있었습니다.gsub하지만 R을 배우는 것을 위해 저는 여전히 제 독창적인 접근법을 얻는 방법을 알고 싶습니다 (가능하다면).

nm를 문자로 변환한 다음 변경하기가 더 쉽습니다.

junk$nm <- as.character(junk$nm)
junk$nm[junk$nm == "B"] <- "b"

편집: 실제로 nm를 요인으로 유지해야 하는 경우 마지막에 다음을 추가합니다.

junk$nm <- as.factor(junk$nm)

가치를 대체하는 또 다른 유용한 방법

library(plyr)
junk$nm <- revalue(junk$nm, c("B"="b"))

간단한 대답은 다음과 같습니다.

junk$nm[junk$nm %in% "B"] <- "b"

R 서론에서 인덱스 벡터를 살펴봅니다(아직 읽지 않은 경우).


편집. 주석에서 알 수 있듯이 이 솔루션은 문자 벡터에 대해 작동하므로 데이터에서 실패합니다.

요인의 경우 가장 좋은 방법은 수준을 변경하는 것입니다.

levels(junk$nm)[levels(junk$nm)=="B"] <- "b"

당신이 보여주는 데이터는 요인들이기 때문에, 그것은 상황을 조금 복잡하게 만듭니다.@diliop의 답변은 다음과 같이 변환하여 문제에 접근합니다.nm문자 변수로 변환합니다.원래 요인으로 돌아가려면 추가 단계가 필요합니다.

또 다른 방법은 요인의 수준을 조정하는 것입니다.

> 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

그것은 매우 간단하고 나는 종종 그것에 대한 대체 기능이 있다는 것을 잊습니다.levels().

편집: @Seth가 코멘트에서 언급한 것처럼, 명확성을 잃지 않고 한 줄로 수행할 수 있습니다.

within(junk, levels(nm)[levels(nm) == "B"] <- "b")

하나의 명령으로 이 작업을 수행하는 가장 쉬운 방법은which명령을 사용하여 요인을 문자로 변경할 필요가 없습니다.

junk$nm[which(junk$nm=="B")]<-"b"

다음에서 요인 변수를 만들었습니다.nm따라서 이를 피하거나 요인 속성에 수준을 추가해야 합니다.또한 사용을 피해야 합니다.<-data.frame에 대한 인수에 있습니다.

옵션 1:

junk <- data.frame(x = rep(LETTERS[1:4], 3), y =letters[1:12], stringsAsFactors=FALSE)
junk$nm[junk$nm == "B"] <- "b"

옵션 2:

levels(junk$nm) <- c(levels(junk$nm), "b")
junk$nm[junk$nm == "B"] <- "b"
junk

사용할 수 있습니다.ifelse또한, 그것은 이해하기 매우 간단합니다.

junk$val <- ifelse(junk$nm == "B", "b", junk$val)

그래도 끝까지 해내고 싶다면,for loop그것을 하는 올바른 방법

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

문자 변수로 작업하는 경우(참고:stringsAsFactors여기서는 false입니다). 바꾸기를 사용할 수 있습니다.

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

저도 같은 문제가 있어요. 각 열에 대해 동일한 작업을 수행할 수도 있습니다.

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

아래 줄을 사용하여 이 함수를 호출합니다.

d=stata.replace(d,"under20",1,"age<20")

언급URL : https://stackoverflow.com/questions/5824173/replace-a-value-in-a-data-frame-based-on-a-conditional-if-statement

반응형