案例陈述相当于R

时间:2011-01-07 02:39:27

标签: r case

我在数据框中有一个变量,其中一个字段通常有7-8个值。我想在数据框中的一个新变量中将它们拼写为3或4个新类别。什么是最好的方法?

如果我使用类似SQL的工具,但是不确定如何在R中攻击它,我会使用CASE语句。

我们非常感谢您提供的任何帮助!

15 个答案:

答案 0 :(得分:26)

查看cases包中的memisc函数。它使用两种不同的方式来实现案例功能。 从包中的示例:

z1=cases(
    "Condition 1"=x<0,
    "Condition 2"=y<0,# only applies if x >= 0
    "Condition 3"=TRUE
    )

其中xy是两个向量。

参考文献:memisc packagecases example

答案 1 :(得分:25)

2016年5月添加到dplyr的

case_when()以与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"
  )
)

答案 2 :(得分:21)

如果你有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"))

答案 3 :(得分:16)

以下是使用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等)。能够在下面定义我们的类别在语法上更方便(参见非常相似的问题How do add a column in a data frame in 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

答案 4 :(得分:14)

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

答案 5 :(得分:13)

我认为没有关于&#39;切换&#39;的建议。代码示例(运行它):

x <- "three";
y <- 0;
switch(x,
       one = {y <- 5},
       two = {y <- 12},
       three = {y <- 432})
y

答案 6 :(得分:6)

您可以使用汽车套餐中的重新编码:

library(ggplot2) #get data
library(car)
daimons$new_var <- recode(diamonds$clarity , "'I1' = 'low';'SI2' = 'low';else = 'high';")[1:10]

答案 7 :(得分:6)

有一个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.numericswitch.character。如果你的第一个参数是一个R'因子',你会得到switch.numeric行为,这可能会导致问题,因为大多数人都会看到显示为字符的因素,并且假设所有函数都会处理它们。< / p>

答案 8 :(得分:5)

我不喜欢其中任何一种,它们对读者或潜在用户来说并不清楚。我只是使用匿名函数,语法不像case语句那样光滑,但评估类似于case语句而不是那么痛苦。这也假设您在定义变量的位置进行评估。

result <- ( function() { if (x==10 | y< 5) return('foo') 
                         if (x==11 & y== 5) return('bar')
                        })()

所有这些()都是封闭和评估匿名函数所必需的。

答案 9 :(得分:3)

混合plyr::mutatedplyr::case_when对我有用并且可读。

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]

如果列可以作为因子而不是char而变异,则获得奖励积分! case_when语句的最后一行捕获所有未匹配的行非常重要。

     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

答案 10 :(得分:2)

案例陈述实际上可能不是正确的方法。如果这是一个可能的因素,只需适当设置因子的水平。

假设你有一个字母A到E的因子,就像这样。

> 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

要加入B级和C级并将其命名为BC,只需将这些级别的名称更改为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

结果符合要求。

答案 11 :(得分:2)

如果你想拥有类似sql的语法,你可以使用sqldf包。要使用的函数也是名称sqldf,语法如下

sqldf(<your query in quotation marks>)

答案 12 :(得分:2)

您可以使用base函数merge进行案例样式重新映射任务:

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

答案 13 :(得分:2)

在这种情况下,我指的是您指的是switch()。它看起来像一个控制语句,但实际上,它是一个函数。对表达式进行求值,并基于此值返回列表中的相应项目。

  

开关以两种不同的方式工作,具体取决于第一个参数是字符串还是数字。

下面是一个简单的字符串示例,该示例解决了将旧类别折叠为新类别的问题。

  

对于字符串形式,在命名值之后有一个未命名的参数作为默认值。

newCat <- switch(EXPR = category,
       cat1   = catX,
       cat2   = catX,
       cat3   = catY,
       cat4   = catY,
       cat5   = catZ,
       cat6   = catZ,
       "not available")

答案 14 :(得分:1)

从data.table v1.13.0开始,您可以使用函数fcase()(快写)执行类似SQL的CASE操作(也类似于dplyr::case_when()):

require(data.table)

dt <- data.table(name = c('cow','pig','eagle','pigeon','cow','eagle'))
dt[ , category := fcase(name %in% c('cow', 'pig'), 'mammal',
                        name %in% c('eagle', 'pigeon'), 'bird') ]
相关问题