【问题标题】:Subsetting a data frame and running calculations in one pass对数据框进行子集化并一次性运行计算
【发布时间】:2019-01-29 14:06:51
【问题描述】:

尝试对数据帧进行子集化,并一次完成一些基本计算,以避免一遍又一遍地复制函数。子集部分正在选择特定的列。并且基本的计算是各个列之间的简单比较。

这是一些数据:

structure(list(name = structure(1:12, .Label = c("a", 
"b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l"), class = "factor"), data_2018 = c(4, 4, 4, 
4, 3, 4, 2, 4, 3, 4, 4, 3), 
data_2017 = c(1, 4, 4, 3, 2, 3, 3, 
4, 2, 1, 1, 2), 
pilot = c(2.68421052631579, 2.73684210526316, 
3.52631578947368, 3.42105263157895, 3.05263157894737, 2.78947368421053, 
2.21052631578947, 3.68421052631579, 2.36842105263158, 3.73684210526316, 
2.47368421052632, 2.05263157894737), 
all = c(2.77777777777778, 
2.85185185185185, 3.62962962962963, 3.51851851851852, 3.18518518518519, 
2.92592592592593, 2.2962962962963, 3.74074074074074, 2.40740740740741, 
3.77777777777778, 2.55555555555556, 2.07407407407407), 
general = c(2.79166666666667, 
2.79166666666667, 3.58333333333333, 3.45833333333333, 3.08333333333333, 
2.83333333333333, 2.41666666666667, 3.70833333333333, 2.54166666666667, 
3.79166666666667, 2.54166666666667, 2.16666666666667), 
tool = c("DoS", 
"DoS", "DoS", "DoS", "DoS", "DoS", "DoS", "DoS", "DoS", "DoS", 
"DoS", "DoS"), status = c(6, 8, 8, 6, 6, 6, 2, 8, 6, 6, 6, 6)), row.names = c(NA, 
12L), class = "data.frame")

这是我尝试过的:

diffs <- select(agged
                , agged$data_2018
                , ifelse(agged$data_2018 >= agged$data_2017, 1, -1)
                , ifelse(agged$data_2018 >= agged$pilot, 1, -1)
                , ifelse(agged$data_2018 >= agged$all, 1, -1)
                , ifelse(agged$data_2018 >= agged$general, 1, -1))

但那是返回

错误 每个参数必须产生正整数或负整数。

希望预期的输出类似于:

data_2018 | vs_data_2017 | vs_pilot | vs_all | vs_general
4         |    1         |    1     |   -1   |    1
4         |    1         |    1     |   -1   |    1
4         |    -1        |    1     |   1   |    1
4         |    -1        |    -1    |   1   |    1
3         |    1         |    -1    |   1   |    1
4         |    -1        |    1     |   1   |    -1

我已经尝试单独运行 ifelse 部分并返回正确整数的向量,所以我不确定还有什么可以尝试的。即使没有dplyr,有没有办法做到这一点?希望没有那个包也能做到这一点。

【问题讨论】:

  • 你的预期输出是什么?
  • 已添加,但与数据不匹配

标签: r


【解决方案1】:

据我了解,这可能是您想要的:

cbind(data_2018 = agged$data_2018, sapply(c("data_2017", "pilot", "all", "general"), function(c) (agged$data_2018 >= agged[[c]]) * 2 - 1))

您根据条件对希望为 -1 或 1 的列应用条件。使用 *2-1 将布尔值 TRUE 或 FALSE 从 0/1 转换为 -1/1。

【讨论】:

  • 谢谢,这很好,但似乎返回了一个列表或矩阵。有没有更好的方法让它返回一个数据框,而不是把as.data.frame() 包裹在整行周围?
  • data.frame(agged$data_2018, sapply(c("data_2017", "pilot", "all", "general"), function(c) (agged$data_2018 &gt;= agged[[c]]) * 2 - 1))
  • 还有一个问题要添加到此功能中。如果我想在所有 data_2017、pilot、all 和 general 之后添加另一列(所以还有 4 列),有没有办法通过添加到原始函数中来做到这一点?所以如果agged[[c]] &gt; 0 那么agged[[c_color]] = "green" else "red"
  • 应该这样做:data.frame(agged$data_2018, sapply(c("data_2017", "pilot", "all", "general"), function(c) (agged$data_2018 &gt;= agged[[c]]) * 2 - 1), col = c("red", "green")[as.numeric(agged$general &gt; 3)+1])
【解决方案2】:

检查这个解决方案:

library(dplyr)

agged %>%
  select(data_2018, data_2017, pilot, all, general) %>%
  mutate_at(2:5, funs(if_else(data_2018 >= ., 1, -1))) %>%
  rename_at(2:5, funs(str_c('vs_', .)))

【讨论】:

    【解决方案3】:
    require(dplyr)
    agged %>% 
      mutate(vs_data_2017 =  if_else(data_2018 >= data_2017, 1, -1),
             vs_pilot     =  if_else(data_2018 >= pilot    , 1, -1),
             vs_all       =  if_else(data_2018 >= all      , 1, -1),
             vs_general   =  if_else(data_2018 >= general  , 1, -1)) %>%
      select(data_2018, vs_data_2017, vs_pilot, vs_all , vs_general) 
    

    【讨论】:

      【解决方案4】:

      根据您的描述,您可以直接使用比较符号(&gt;=),即

      (dd$data_2018 >= dd[3:6]) * 1
      
      #   data_2017 pilot all general
      #1          1     1   1       1
      #2          1     1   1       1
      #3          1     1   1       1
      #4          1     1   1       1
      #5          1     0   0       0
      #6          1     1   1       1
      #7          0     0   0       0
      #8          1     1   1       1
      #9          1     1   1       1
      #10         1     1   1       1
      #11         1     1   1       1
      #12         1     1   1       1
      

      注意:我改为转换为 0 和 1。您可以轻松地将其更改为 1 和 -1

      【讨论】:

      • 我喜欢这个,但我收到与列数不匹配有关的错误。 length of 'dimnames' [2] not equal to array extent
      • 嗯...我也不确定它为什么会抛出该错误
      猜你喜欢
      • 1970-01-01
      • 2022-12-09
      • 2023-03-22
      • 1970-01-01
      • 1970-01-01
      • 2013-08-15
      • 1970-01-01
      • 1970-01-01
      • 2017-04-06
      相关资源
      最近更新 更多