R에서 동등한 Case 문
필드 중 하나에 일반적으로 7-8 개의 값이있는 데이터 프레임에 변수가 있습니다. 데이터 프레임 내의 새 변수 내에서 3 개 또는 4 개의 새 범주를 축소하고 싶습니다. 가장 좋은 방법은 무엇입니까?
SQL과 같은 도구를 사용했지만 R에서 이것을 공격하는 방법을 잘 모르겠다면 CASE 문을 사용합니다.
당신이 제공 할 수있는 어떤 도움이라도 대단히 감사 할 것입니다!
패키지 의 cases
기능을 살펴보십시오 memisc
. 사용하는 두 가지 방법으로 케이스 기능을 구현합니다. 패키지의 예에서 :
z1=cases(
"Condition 1"=x<0,
"Condition 2"=y<0,# only applies if x >= 0
"Condition 3"=TRUE
)
여기서, x
그리고 y
두 개의 벡터이다.
참조 : memisc 패키지 , 사례 예
case_when()
2016 년 5 월에 dplyr에 추가 된은 memisc::cases()
.
예를 들면 :
library(dplyr)
mtcars %>%
mutate(category = case_when(
.$cyl == 4 & .$disp < median(.$disp) ~ "4 cylinders, small displacement",
.$cyl == 8 & .$disp > median(.$disp) ~ "8 cylinders, large displacement",
TRUE ~ "other"
)
)
dplyr 0.7.0부터,
mtcars %>%
mutate(category = case_when(
cyl == 4 & disp < median(disp) ~ "4 cylinders, small displacement",
cyl == 8 & disp > median(disp) ~ "8 cylinders, large displacement",
TRUE ~ "other"
)
)
그렇다면 factor
표준 방법으로 수준을 변경할 수 있습니다.
df <- data.frame(name = c('cow','pig','eagle','pigeon'),
stringsAsFactors = FALSE)
df$type <- factor(df$name) # First step: copy vector and make it factor
# Change levels:
levels(df$type) <- list(
animal = c("cow", "pig"),
bird = c("eagle", "pigeon")
)
df
# name type
# 1 cow animal
# 2 pig animal
# 3 eagle bird
# 4 pigeon bird
간단한 함수를 래퍼로 작성할 수 있습니다.
changelevels <- function(f, ...) {
f <- as.factor(f)
levels(f) <- list(...)
f
}
df <- data.frame(name = c('cow','pig','eagle','pigeon'),
stringsAsFactors = TRUE)
df$type <- changelevels(df$name, animal=c("cow", "pig"), bird=c("eagle", "pigeon"))
switch
문을 사용하는 방법은 다음과 같습니다 .
df <- data.frame(name = c('cow','pig','eagle','pigeon'),
stringsAsFactors = FALSE)
df$type <- sapply(df$name, switch,
cow = 'animal',
pig = 'animal',
eagle = 'bird',
pigeon = 'bird')
> df
name type
1 cow animal
2 pig animal
3 eagle bird
4 pigeon bird
이것의 한 가지 단점은 animal
각 항목에 대해 카테고리 이름 ( 등) 을 계속 작성해야한다는 것 입니다. 아래와 같이 범주를 정의 할 수있는 것이 구문 적으로 더 편리합니다 ( R의 데이터 프레임에 열을 추가하는 방법은 매우 유사한 질문 참조 )
myMap <- list(animal = c('cow', 'pig'), bird = c('eagle', 'pigeon'))
어떻게 든이 매핑을 "반전"하고 싶습니다. 내 자신의 invMap 함수를 작성합니다.
invMap <- function(map) {
items <- as.character( unlist(map) )
nams <- unlist(Map(rep, names(map), sapply(map, length)))
names(nams) <- items
nams
}
그런 다음 위의지도를 다음과 같이 반전합니다.
> invMap(myMap)
cow pig eagle pigeon
"animal" "animal" "bird" "bird"
그리고 이것을 사용 type
하여 데이터 프레임에 열 을 추가하는 것은 쉽습니다 .
df <- transform(df, type = invMap(myMap)[name])
> df
name type
1 cow animal
2 pig animal
3 eagle bird
4 pigeon bird
Imho, 가장 간단하고 보편적 인 코드 :
dft=data.frame(x = sample(letters[1:8], 20, replace=TRUE))
dft=within(dft,{
y=NA
y[x %in% c('a','b','c')]='abc'
y[x %in% c('d','e','f')]='def'
y[x %in% 'g']='g'
y[x %in% 'h']='h'
})
'스위치'에 대한 제안이 보이지 않습니다. 코드 예제 (실행) :
x <- "three";
y <- 0;
switch(x,
one = {y <- 5},
two = {y <- 12},
three = {y <- 432})
y
거기에있다 switch
문하지만 나는 내가 그것을해야한다 생각하는 방식으로 작동 얻을 수가 없다. 예제를 제공하지 않았으므로 요인 변수를 사용하여 하나를 만들 것입니다.
dft <-data.frame(x = sample(letters[1:8], 20, replace=TRUE))
levels(dft$x)
[1] "a" "b" "c" "d" "e" "f" "g" "h"
재 할당에 적합한 순서로 원하는 범주를 지정하는 경우 요인 또는 숫자 변수를 인덱스로 사용할 수 있습니다.
c("abc", "abc", "abc", "def", "def", "def", "g", "h")[dft$x]
[1] "def" "h" "g" "def" "def" "abc" "h" "h" "def" "abc" "abc" "abc" "h" "h" "abc"
[16] "def" "abc" "abc" "def" "def"
dft$y <- c("abc", "abc", "abc", "def", "def", "def", "g", "h")[dft$x] str(dft)
'data.frame': 20 obs. of 2 variables:
$ x: Factor w/ 8 levels "a","b","c","d",..: 4 8 7 4 6 1 8 8 5 2 ...
$ y: chr "def" "h" "g" "def" ...
나중에 두 가지 다른 스위치 기능이 있다는 것을 알게되었습니다. 일반적인 기능은 아니지만 switch.numeric
또는 로 생각해야합니다 switch.character
. 첫 번째 인수가 R '인자'인 switch.numeric
경우 대부분의 사람들이 요소가 문자로 표시되고 모든 함수가이를 처리 할 것이라는 잘못된 가정을하기 때문에 문제를 일으킬 가능성 이있는 행동이 발생합니다.
자동차 패키지에서 레코딩을 사용할 수 있습니다.
library(ggplot2) #get data
library(car)
daimons$new_var <- recode(diamonds$clarity , "'I1' = 'low';'SI2' = 'low';else = 'high';")[1:10]
i dont like any of these, they are not clear to the reader or the potential user. I just use an anonymous function, the syntax is not as slick as a case statement, but the evaluation is similar to a case statement and not that painful. this also assumes your evaluating it within where your variables are defined.
result <- ( function() { if (x==10 | y< 5) return('foo')
if (x==11 & y== 5) return('bar')
})()
all of those () are necessary to enclose and evaluate the anonymous function.
I am using in those cases you are referring switch()
. It looks like a control statement but actually, it is a function. The expression is evaluated and based on this value, the corresponding item in the list is returned.
switch works in two distinct ways depending whether the first argument evaluates to a character string or a number.
What follows is a simple string example which solves your problem to collapse old categories to new ones.
For the character-string form, have a single unnamed argument as the default after the named values.
newCat <- switch(EXPR = category,
cat1 = catX,
cat2 = catX,
cat3 = catY,
cat4 = catY,
cat5 = catZ,
cat6 = catZ,
"not available")
A case statement actually might not be the right approach here. If this is a factor, which is likely is, just set the levels of the factor appropriately.
Say you have a factor with the letters A to E, like this.
> a <- factor(rep(LETTERS[1:5],2))
> a
[1] A B C D E A B C D E
Levels: A B C D E
To join levels B and C and name it BC, just change the names of those levels to BC.
> levels(a) <- c("A","BC","BC","D","E")
> a
[1] A BC BC D E A BC BC D E
Levels: A BC D E
The result is as desired.
If you want to have sql-like syntax you can just make use of sqldf
package. Tthe function to be used is also names sqldf
and the syntax is as follows
sqldf(<your query in quotation marks>)
You can use the base
function merge
for case-style remapping tasks:
df <- data.frame(name = c('cow','pig','eagle','pigeon','cow','eagle'),
stringsAsFactors = FALSE)
mapping <- data.frame(
name=c('cow','pig','eagle','pigeon'),
category=c('animal','animal','bird','bird')
)
merge(df,mapping)
# name category
# 1 cow animal
# 2 cow animal
# 3 eagle bird
# 4 eagle bird
# 5 pig animal
# 6 pigeon bird
Mixing plyr::mutate
and dplyr::case_when
works for me and is readable.
iris %>%
plyr::mutate(coolness =
dplyr::case_when(Species == "setosa" ~ "not cool",
Species == "versicolor" ~ "not cool",
Species == "virginica" ~ "super awesome",
TRUE ~ "undetermined"
)) -> testIris
head(testIris)
levels(testIris$coolness) ## NULL
testIris$coolness <- as.factor(testIris$coolness)
levels(testIris$coolness) ## ok now
testIris[97:103,4:6]
Bonus points if the column can come out of mutate as a factor instead of char! The last line of the case_when statement, which catches all un-matched rows is very important.
Petal.Width Species coolness
97 1.3 versicolor not cool
98 1.3 versicolor not cool
99 1.1 versicolor not cool
100 1.3 versicolor not cool
101 2.5 virginica super awesome
102 1.9 virginica super awesome
103 2.1 virginica super awesome
참고URL : https://stackoverflow.com/questions/4622060/case-statement-equivalent-in-r
'program story' 카테고리의 다른 글
Visual Studio의 소스 제어 통합은 Perforce와 어떻게 작동합니까? (0) | 2020.10.29 |
---|---|
컨트롤러에서 레이크 작업 실행 (0) | 2020.10.29 |
Xcode 4.2 한 프로젝트를 다른 프로젝트에 어떻게 포함합니까? (0) | 2020.10.29 |
오버플로가 숨겨진 작은 div 안에 알 수없는 크기의 큰 이미지를 중앙에 배치 (0) | 2020.10.29 |
Vue.js 알 수없는 맞춤 요소 (0) | 2020.10.29 |