【问题标题】:Using case_when to subset a datatable使用 case_when 对数据表进行子集化
【发布时间】:2019-10-16 21:18:48
【问题描述】:

我还是 R 的新手,我遇到了一个问题。 我有一个包含原始数据的文件:

dfRawData <-
  data.table(
    "Model" = c(
      "Car1",
      "Car1",
      "Car1",
      "Car2",
      "Car2",
      "Car2",
      "Car3",
      "Car3",
      "Car3"
    ),
    "variable" = c(
      "Metric1",
      "Metric2",
      "Metric3",
      "Metric1",
      "Metric2",
      "Metric3",
      "Metric1",
      "Metric2",
      "Metric3"
    ),
    "valeur" = c(1, 2, 3, 4, 5, 6, 7, 8, 9)
  )

我想根据汽车名称和指标对该数据表进行子集化。但是,我想避免使用 if 语句,因为我的代码已经很长了。据我了解, case_when 可能非常有用。 我知道子集数据表的公式是正确的,因为当我使用 if 语句时,它会返回我想要的。 然而,当我使用 case_when 时,出现以下错误:

Error in `[.data.frame`(x, i) : undefined columns selected

有人知道我做错了什么吗? 这是我的代码:

carName = 'Car1' ##Can be changed
dfCarMetric = case_when(
           carName == 'Car1' ~ dfRawData[which(dfRawData[["Model"]] == carName  &
                                               dfRawData[["variable"]] %in% c("Metric1", "Metric2")), ],
           carName == 'Car2' ~ dfRawData[which(dfRawData[["Model"]] %in% c("Car2", "Car3")  &
                                               dfRawData[["variable"]] == "Metric1"), ]
       )

我想最后拥有这个:

carName = 'Car1'
    dfCarMetric
       Model variable valeur
    1:  Car1  Metric1      1
    2:  Car1  Metric2      2

carName = 'Car2'
    dfCarMetric
      Model variable valeur
    4  Car2  Metric1      4
    7  Car3  Metric1      7

非常感谢您的回答!!

【问题讨论】:

  • 如果您包含一个简单的reproducible example,其中包含可用于测试和验证可能解决方案的示例输入和所需输出,则更容易为您提供帮助。请勿发布数据图片。我们无法复制/粘贴它进行测试。
  • 请以纯文本形式包含您的数据的代表性样本 - see here for how。图片中的数据不能被其他用户复制/粘贴。

标签: r datatable


【解决方案1】:

如果您想尽量减少条件语句的数量,您可以在 filter 函数中使用它们,同样来自 dplyr 包:

dfCarMetric <- dfRawData %>% 
  filter(
    if (carName == "Car1") 
      Model == carName & variable %in% c("Metric1", "Metric2") 
    else if (carName == "Car2") 
      Model %in% c("Car2", "Car3") & variable == "Metric1")
  )

case_when 函数可以以类似的方式使用,尽管不太常见,恕我直言:

dfCarMetric <- dfRawData %>% 
  filter(case_when(
      carName == "Car1" ~
        Model == carName & variable %in% c("Metric1", "Metric2"), 
      carName == "Car2" ~
        Model %in% c("Car2", "Car3") & variable == "Metric1"
    )
  )

【讨论】:

    【解决方案2】:

    而不是case_when,我想它来自包dplyr,你为什么不尝试filter函数,它更适合子设置数据集。

    library(dplyr)
    library(magrittr)
    
    dfRawData <-  data.frame(
        "Model" = c(
          "Car1",
          "Car1",
          "Car1",
          "Car2",
          "Car2",
          "Car2",
          "Car3",
          "Car3",
          "Car3"
        ),
        "variable" = c(
          "Metric1",
          "Metric2",
          "Metric3",
          "Metric1",
          "Metric2",
          "Metric3",
          "Metric1",
          "Metric2",
          "Metric3"
        ),
        "valeur" = c(1, 2, 3, 4, 5, 6, 7, 8, 9)
      )
    
    # Filter
    newData <- dfRawData %>% 
      filter((Model =='Car1' & variable %in% c('Metric1', 'Metric2')) |  # Condition 1
                         (Model %in% c('Car2', 'Car3') & variable == 'Metric1')) # Condition 2
    

    这会产生如下输出:

     newData
      Model variable valeur
    1  Car1  Metric1      1
    2  Car1  Metric2      2
    3  Car2  Metric1      4
    4  Car3  Metric1      7
    

    您可以调整filter 条件以获得您喜欢的确切子集,它应该是比case_when 更简单的语法。

    使用函数


    为了使这更容易一点并允许您指定carName,您可以将此特定过滤器包装到一个简单(尽管很脆弱)的函数中:

    myFilterFunction <- function(data, carName = 'Car1', metric = c('Metric1', 'Metric2')) {
      data %>%
        filter(Model %in% carName & variable %in% metric)
    }
    
    carName = 'Car1'
    myFilterFunction(dfRawData, carName = carName, c('Metric1', 'Metric2'))
    
    carName = c('Car2', 'Car3')
    myFilterFunction(dfRawData, carName = carName, c('Metric1'))
    

    输出如下:

      Model variable valeur
    1  Car1  Metric1      1
    2  Car1  Metric2      2
    
      Model variable valeur
    1  Car2  Metric1      4
    2  Car3  Metric1      7
    

    【讨论】:

    • 但是如果我使用filter 函数,我的输出不依赖于carName ...
    • 请参阅编辑,其中包括如何将 carName 指定为函数的输入以确定所需的输出。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-23
    • 1970-01-01
    相关资源
    最近更新 更多