필드 중 하나에 일반적으로 7-8 개의 값이있는 데이터 프레임에 변수가 있습니다. 데이터 프레임 내의 새 변수 내에서 3 개 또는 4 개의 새 범주를 축소하고 싶습니다. 가장 좋은 방법은 무엇입니까?
SQL과 같은 도구를 사용했지만 R에서 이것을 공격하는 방법을 잘 모르겠다면 CASE 문을 사용합니다.
당신이 제공 할 수있는 어떤 도움이라도 대단히 감사 할 것입니다!
답변
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"
)
)
답변
패키지 의 cases
기능을 살펴보십시오 memisc
. 사용하는 두 가지 방법으로 케이스 기능을 구현합니다. 패키지의 예에서 :
z1=cases(
"Condition 1"=x<0,
"Condition 2"=y<0,# only applies if x >= 0
"Condition 3"=TRUE
)
여기서, x
그리고 y
두 개의 벡터이다.
참조 : memisc 패키지 , 사례 예
답변
그렇다면 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
답변
‘스위치’에 대한 제안이 보이지 않습니다. 코드 예제 (실행) :
x <- "three"
y <- 0
switch(x,
one = {y <- 5},
two = {y <- 12},
three = {y <- 432})
y
답변
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'
})
답변
거기에있다 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
경우 대부분의 사람들은 요인이 문자로 표시되고 모든 함수가이를 처리 할 것이라는 잘못된 가정을하기 때문에 문제를 일으킬 가능성 이있는 행동이 발생합니다.