【问题标题】:How can I make conditional selections using dplyr in R?如何在 R 中使用 dplyr 进行条件选择?
【发布时间】:2018-09-21 08:33:27
【问题描述】:

我有以下情况。给定表格

df <- data.frame(ID = c(1, 2, 2, 3, 3, 4),
             type = c("MC", "MC", "MK", "MC", "MK", "MC"),
             value1 = c(512, 261, 4523, 1004, 1221, 2556),
             value2 = c(726, 4000, 280, 998, 113, 6789))

我正在尝试找到一种方法来实现以下逻辑:如果对于一个 ID,两种类型(MC 和 MK)都出现,则使用 MK 中的 value1 和 MC 中的 value2。否则(仅出现类型 MC),使用 MC。

因此,最终结果应该是:

data.frame(ID = c(1, 2, 3, 4),
             type = c("MC", "MC", "MC", "MC"),
             value1 = c(512, 4523, 1221, 2556),
             value2 = c(726, 4000, 998, 6789))

假设类型 MK 在提取 value1 后被丢弃。

【问题讨论】:

  • 第二个df:Error in data.frame(ID = c(1, 2, 2, 3, 3, 4), type = c("MC", "MC", "MC", : arguments imply differing number of rows: 6, 4
  • @Andre 谢谢 - 现在是正确的。

标签: r group-by dplyr


【解决方案1】:

另一个带有dplyr的版本

library(dplyr)

df %>%
  group_by(ID) %>%
  mutate(value1 = ifelse(any(type == "MK"), value1[type=="MK"],value1[type=="MC"]), 
         value2 = value2[type == "MC"]) %>%
  filter(type == "MC")

#     ID type  value1 value2
#  <dbl> <fct>  <dbl>  <dbl>
#1     1 MC       512    726
#2     2 MC      4523   4000
#3     3 MC      1221    998
#4     4 MC      2556   6789

在这里,对于value1,我们检查“MK”中的值是否存在,或者取而代之的是相应的“MC”值,而对于value2,默认情况下我们采用“MC”值并只保留带有type的行MC”。这是假设每个组 (ID) 都会有一个“MC”type 行。

【讨论】:

    【解决方案2】:

    为了提高效率,我肯定更喜欢@Andre Elrico 的回答,但这里有一个dplyr 选项。试试:

    df <- data.frame(ID = c(1, 2, 2, 3, 3, 4),
                     type = c("MC", "MC", "MK", "MC", "MK", "MC"),
                     value1 = c(512, 261, 4523, 1004, 1221, 2556),
                     value2 = c(726, 4000, 280, 998, 113, 6789)) 
    library(dplyr)
    df %>%
      reshape(., idvar = "ID", timevar = "type", direction = "wide") %>%
      group_by(ID) %>%
      mutate(value1 = ifelse(is.na(value1.MK), value1.MC, value1.MK),
             value2 = ifelse(is.na(value2.MC), value2.MK, value2.MC),
             type = "MC") %>%
      select(ID, type, value1, value2)
    # output
    # A tibble: 4 x 4
    # Groups:   ID [4]
         ID  type value1 value2
      <dbl> <chr>  <dbl>  <dbl>
    1     1    MC    512    726
    2     2    MC   4523   4000
    3     3    MC   1221    998
    4     4    MC   2556   6789
    

    【讨论】:

      【解决方案3】:

      data.table解决方案

      setDT(df1)[,{x=.SD;if(all(c("MC","MK") %in% type)){x$value1[] = last(value1)};first(x)},by=ID]
      

      结果:

      #  ID type value1 value2
      #1  1   MC    512    726
      #2  2   MC   4523   4000
      #3  3   MC   1221    998
      #4  4   MC   2556   6789
      

      dplyr:

      df1 %>% group_by(ID) %>% do(.,(function(x){if(all(c("MC","MK") %in% x$type)){x$value1[] = x$value1[x$type=="MK"]};x[1,]})(.))
      
      # A tibble: 4 x 4
      # Groups:   ID [4]
      #     ID type  value1 value2
      #  <dbl> <fct>  <dbl>  <dbl>
      #1     1 MC       512    726
      #2     2 MC      4523   4000
      #3     3 MC      1221    998
      #4     4 MC      2556   6789
      

      【讨论】:

      • @安德烈。非常感谢您提供可能的解决方案。我更喜欢 dplyr 的解决方案,但这绝对是一个好的开始。干杯
      猜你喜欢
      • 2019-03-09
      • 2018-03-10
      • 1970-01-01
      • 2022-08-02
      • 2020-03-28
      • 1970-01-01
      • 1970-01-01
      • 2019-06-30
      • 2023-03-30
      相关资源
      最近更新 更多