如何使用if条件检查多个值

时间:2018-10-30 12:44:43

标签: r dplyr

我喜欢下面提到的数据框:

记录:

ID        Remarks         Value
1         ABC             10
1         AAB             12
1         ZZX             15
2         XYZ             12
2         ABB             14

通过利用上述数据框,我想在现有数据框中添加新列Status

如果Remarks是ABC,AAB或ABB,则状态为TRUE,对于XYZ和ZZX应该为FALSE

我正在使用下面提到的方法,但这没用。

Records$Status<-ifelse(Records$Remarks %in% ("ABC","AAB","ABB"),"TRUE",
                             ifelse(Records$Remarks %in% 
                      ("XYZ","ZZX"),"FALSE"))

并且,基于Status,我想得出以下输出:

ID     TRUE    FALSE    Sum
1       2       1        37
2       1       1        26

4 个答案:

答案 0 :(得分:2)

Records$Status<-ifelse(Records$Remarks %in% c("ABC","AAB","ABB"),TRUE,
                        ifelse(Records$Remarks %in% 
                                   c("XYZ","ZZX"),FALSE, NA))

您需要用c()括起字符串列表,并为第二个ifelse添加一个“ else”条件(但请参见下面的Roman答案,以更好的方式使用case_when)。 (还要注意,这里我将"TRUE""FALSE"(作为字符类)更改为TRUEFALSE(逻辑类)。

有关摘要(使用dplyr):

Records %>% group_by(ID) %>% 
dplyr::summarise(trues=sum(Status), falses=sum(!Status), sum=sum(Value))

# A tibble: 2 x 4
     ID trues falses   sum
  <int> <int>  <int> <int>
1     1     2      1    37
2     2     1      1    26

当然,如果您实际上不需要中间的“状态”列,而只需要汇总表,则可以完全跳过第一步:

Records %>% group_by(ID) %>% 
dplyr::summarise(trues=sum(Remarks %in% c("ABC","AAB","ABB")), 
  falses=sum(Remarks %in% c("XYZ","ZZX")), 
  sum=sum(Value))

答案 1 :(得分:1)

由于在第二个问题中使用dplyr是有意义的(请参阅@iod的答案),所以在第一部分中使用包的非常简单的case_when()函数也是一个很好的机会。

Records %>% 
    mutate(Status = case_when(Remarks %in% c("ABC", "AAB", "ABB") ~ TRUE,
                              Remarks %in% c("XYZ", "ZZX") ~ FALSE,
                              TRUE ~ NA))

  ID Remarks Value Status
1  1     ABC    10   TRUE
2  1     AAB    12   TRUE
3  1     ZZX    15  FALSE
4  2     XYZ    12  FALSE
5  2     ABB    14   TRUE

答案 2 :(得分:0)

在大多数情况下,没有ifelse,生活会更轻松,行会更短:

# short version
df$Status <- df$Remarks %in% c("ABC","AAB","ABB")  

此版本可用于大多数用途,但有缺点。如果StatusFALSE,或者说Remarks,则NA将是"garbage",但在这种情况下,您可能希望它成为NA,{{ 1}}(仅适用于FALSE)。因此,可以将条件相加并相乘,最后将其转换为Remarks %in% c("XYZ", "ZZX")

logical

以R为底的汇总表:

df$Status <- as.logical(with(df,
                  Remarks %in% c("ABC","AAB","ABB")  +
                  ! Remarks %in% c("XYZ","ZZX") ))

嗯...也许有些格式会有用:

aggregate(df[,-(1:2)], df["ID"], function(x) if(is.numeric(x)) sum(x) else table(x))

答案 3 :(得分:0)

此返回正确的结果,仅当有两个提到的组(<fieldset id="test1"> <div>some content</div> <h1>Heading One</h1> <div>some content</div> </fieldset> <br> <fieldset id="test2"> <div>some content</div> <h1>Heading One</h1> <div>some content</div> </fieldset>"ABC", "AAB", "ABB")时。对我来说,@ iod的解决方案更像"XYZ","ZZX", ...,但我尝试避免使用R,而是采用另一种方式:

代码:

ifelse

数据:

library(tidyverse)

dt %>%
  group_by(ID, Status = grepl("^A[AB][CB]$", Remarks)) %>%
  summarise(N = n(), Sum = sum(Value)) %>%
  spread(Status, N) %>%
  summarize_all(sum, na.rm = T) %>%                       # data still groupped by ID
  select("ID", "TRUE", "FALSE", "Sum")

# A tibble: 2 x 4
     ID `TRUE` `FALSE`   Sum
  <int>  <int>   <int> <int>
1     1      2       1    37
2     2      1       1    26