【问题标题】:Complex dataframe values selection based on both rows and columns基于行和列的复杂数据框值选择
【发布时间】:2018-12-22 19:39:42
【问题描述】:

我需要在下面数据集的每个上选择一些计算一个总和

这是我的数据集的一部分。

> prova
   key_duration1 key_duration2 key_duration3 KeyPress1RESP KeyPress2RESP KeyPress3RESP
18          3483           364          3509             b             n             m
19          2367           818          3924             b             n             m
20          3775          1591           802             b             m             n
21           929          3059           744             n             b             n
22          3732           530          1769             b             n             m
23          3503          2011          2932             b             n             b
24          3684          1424          1688             b             n             m

行是实验的试验,列是按下的键,按时间顺序 (keypressRESP) 和键到下一个键的时间量 (key_duration)。

例如,在第一次试验(第一行)中,我按下“b”,3483 毫秒后按下“n”,依此类推。
这是我的数据框

structure(list(key_duration1 = c(3483L, 2367L, 3775L, 929L, 3732L, 
3503L, 3684L), key_duration2 = c(364L, 818L, 1591L, 3059L, 530L, 
2011L, 1424L), key_duration3 = c(3509, 3924, 802, 744, 1769, 
2932, 1688), KeyPress1RESP = structure(c(2L, 2L, 2L, 4L, 2L, 
2L, 2L), .Label = c("", "b", "m", "n"), class = "factor"), KeyPress2RESP = structure(c(4L, 
4L, 3L, 2L, 4L, 4L, 4L), .Label = c("", "b", "m", "n"), class = "factor"), 
    KeyPress3RESP = structure(c(3L, 3L, 4L, 4L, 3L, 2L, 3L), .Label = c("", 
    "b", "m", "n"), class = "factor")), row.names = 18:24, class = "data.frame")

我需要一种在每一行(试用)中选择所有“b”值的方法,计算 sum(key_duration) 并在新列上打印这些值,“m”也是如此。

我该怎么办?

我认为我需要一个类似于 'apply()' 但不计算行上的每个值而只计算选定值的函数。

apply(prova[,1:3],1,sum)

谢谢

【问题讨论】:

  • 请查看How to make a great R reproducible example,以修改您的问题,并从您的数据中提取较小的样本(check?dput())。发布您的数据或没有数据的图像会使我们难以为您提供帮助!
  • @massisenergy 感谢您的提示,对不起,我不擅长这个领域。我尝试修改问题,并添加了 dput() 输出。
  • @FilippoGambarota 您能否也显示预期的输出?你提到了"b""m" - 那么"n" 呢?
  • @markus 我需要一个类似 apply() 的函数,但我不必对行的所有值求和,而只是对“b”值求和,并将这些值添加到新列上,“m”也是如此价值观。我不需要“n”个值。
  • 您的列固定了吗?我的意思是,示例数据中是否还有这些列(例如,key_duration4keypress4RESP)?

标签: r dataframe


【解决方案1】:

这是一种使用data.table的方法。

library(data.table)
setDT(prova)

# melt
prova_long <-
  melt(
    prova[, idx := 1:.N],
    id.vars = "idx",
    measure.vars = patterns("^key_duration", "^KeyPress"),
    variable.name = "key",
    value.name = c("duration", "RESP")
  )

# aggregate
prova_aggr <- prova_long[RESP != "n", .(duration_sum = sum(duration)), by = .(idx, RESP)]

# spread and join
prova[dcast(prova_aggr, idx ~ paste0("sum_", RESP)), c("sum_b", "sum_m") := .(sum_b, sum_m), on = "idx"]
prova

结果

#   key_duration1 key_duration2 key_duration3 KeyPress1RESP KeyPress2RESP KeyPress3RESP idx sum_b sum_m
#1:          3483           364          3509             b             n             m   1  3483  3509
#2:          2367           818          3924             b             n             m   2  2367  3924
#3:          3775          1591           802             b             m             n   3  3775  1591
#4:           929          3059           744             n             b             n   4  3059    NA
#5:          3732           530          1769             b             n             m   5  3732  1769
#6:          3503          2011          2932             b             n             b   6  6435    NA
#7:          3684          1424          1688             b             n             m   7  3684  1688

我们的想法是将您的数据重塑为长格式,按每行“RESP”聚合。传播结果并加入您的初始数据。

【讨论】:

    【解决方案2】:

    使用tidyverse,您可以:

    bind_cols(df %>%
     select_at(vars(starts_with("KeyPress"))) %>%
     rowid_to_column() %>%
     gather(var, val, -rowid), df %>%
     select_at(vars(starts_with("key_"))) %>%
     rowid_to_column() %>%
     gather(var, val, -rowid)) %>%
     group_by(rowid) %>%
     summarise(b_values = sum(val1[val == "b"]),
               m_values = sum(val1[val == "m"])) %>%
     left_join(df %>%
                rowid_to_column(), by = c("rowid" = "rowid")) %>%
     ungroup() %>%
     select(-rowid)
    
      b_values m_values key_duration1 key_duration2 key_duration3 KeyPress1RESP KeyPress2RESP KeyPress3RESP
         <dbl>    <dbl>         <int>         <int>         <dbl> <fct>         <fct>         <fct>        
    1    3483.    3509.          3483           364         3509. b             n             m            
    2    2367.    3924.          2367           818         3924. b             n             m            
    3    3775.    1591.          3775          1591          802. b             m             n            
    4    3059.       0.           929          3059          744. n             b             n            
    5    3732.    1769.          3732           530         1769. b             n             m            
    6    6435.       0.          3503          2011         2932. b             n             b            
    7    3684.    1688.          3684          1424         1688. b             n             m  
    

    首先,它将df分成两部分:一个带有以“KeyPress”开头的变量,另一个带有以“key_”开头的变量。其次,它将两个dfs从宽格式转换为长格式,并按列组合它们。第三,它根据行 ID 创建“b”和“m”值的摘要。最后,将结果与原始 df 合并。

    【讨论】:

      【解决方案3】:

      您可以从KeyPress 列创建一个逻辑矩阵,将其乘以key_duration 子集,然后取其rowSums

      prova$b_values <- rowSums((prova[, 4:6] == "b") * prova[, 1:3])
      prova$n_values <- rowSums((prova[, 4:6] == "n") * prova[, 1:3])
      
      
         key_duration1 key_duration2 key_duration3 KeyPress1RESP KeyPress2RESP KeyPress3RESP b_values n_values
      18          3483           364          3509             b             n             m     3483     364
      19          2367           818          3924             b             n             m     2367     818
      20          3775          1591           802             b             m             n     3775     802
      21           929          3059           744             n             b             n     3059    1673
      22          3732           530          1769             b             n             m     3732     530
      23          3503          2011          2932             b             n             b     6435    2011
      24          3684          1424          1688             b             n             m     3684    1424
      

      之所以有效,是因为逻辑值被强制转换为数字 1 或 0,并且仅保留单个键的值。

      额外:概括地说,您可以改用函数和tidyverse/purrr 来映射它:

      get_sums <- function(key) rowSums((prova[, 4:6] == key) * prova[, 1:3])
      keylist <- list(b_values = "b", n_values = "n", m_values = "m")
      
      library(tidyverse)
      bind_cols(prova, map_dfr(keylist, get_sums))
      

      【讨论】:

        猜你喜欢
        • 2016-11-02
        • 1970-01-01
        • 2023-01-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-03-04
        • 1970-01-01
        相关资源
        最近更新 更多