【问题标题】:Detecting identical observations across columns in R dataframe在 R 数据框中跨列检测相同的观察值
【发布时间】:2019-10-09 18:50:29
【问题描述】:

在 R 中的数据框中,我试图检测 5 个连续观察值在伪随机设计中是否相同。

在这个设计中,两类对象被呈现 5 次(A 对象和 B 对象),参与者对它们进行评分(A1 - B5)。每个对象的排序也包含在列中(A1.order - B5.order)。我想知道的是 5 个连续的观察值(可以是前 5 个、中间 5 个、最后 5 个等)是否相同。用于检测列是否相同的典型功能在这里不起作用,因为我担心对象的呈现顺序。

我希望将一个名为“相同”的新列添加到数据框中,这将为我提供关于是否有 5 个相同的连续观察值的 TRUE 或 FALSE。

我还希望将这些相同的观察结果编码为“NA”

df <- structure(list(ID = c(101, 102, 103, 104, 105, 106, 107), A1 = c(1, 
4, 1, 3, 4, 5, 3), A2 = c(1, 3, 1, 1, 5, 3, 2), A3 = c(1, 1, 
1, 5, 4, 3, 2), A4 = c(1, 3, 2, 1, 3, 2, 1), A5 = c(3, 1, 2, 
3, 5, 4, 5), B1 = c(3, 2, 1, 5, 1, 3, 2), B2 = c(1, 2, 1, 4, 
2, 4, 5), B3 = c(1, 2, 3, 2, 5, 4, 3), B4 = c(2, 3, 1, 4, 5, 
2, 3), B5 = c(2, 2, 2, 2, 2, 2, 2), A1.order = c(1, 2, 1, 2, 
1, 2, 1), A2.order = c(3, 4, 3, 4, 3, 4, 3), A3.order = c(5, 
6, 5, 6, 5, 6, 5), A4.order = c(7, 8, 7, 8, 7, 8, 7), A5.order = c(10, 
9, 10, 9, 10, 9, 10), B1.order = c(2, 1, 2, 1, 2, 1, 2), B2.order = c(4, 
3, 4, 3, 4, 3, 4), B3.order = c(6, 5, 6, 5, 6, 5, 6), B4.order = c(8, 
7, 8, 7, 8, 7, 8), B5.order = c(9, 10, 9, 10, 9, 10, 9)), row.names = c(NA, 
7L), class = "data.frame")

df

#>    ID A1 A2 A3 A4 A5 B1 B2 B3 B4 B5 A1.order A2.order A3.order A4.order
#> 1 101  1  2  3  4  3  3  1  1  2  2        1        3        5        7
#> 2 102  4  3  1  3  1  2  2  2  3  2        2        4        6        8
#> 3 103  2  4  3  2  2  4  3  3  1  2        1        3        5        7
#> 4 104  3  1  5  1  3  5  4  2  4  2        2        4        6        8
#> 5 105  4  5  4  3  5  1  2  5  5  2        1        3        5        7
#> 6 106  5  3  3  2  4  3  4  4  2  2        2        4        6        8
#> 7 107  3  2  2  1  5  2  5  3  3  2        1        3        5        7
#>   A5.order B1.order B2.order B3.order B4.order B5.order
#> 1       10        2        4        6        8        9
#> 2        9        1        3        5        7       10
#> 3       10        2        4        6        8        9
#> 4        9        1        3        5        7       10
#> 5       10        2        4        6        8        9
#> 6        9        1        3        5        7       10
#> 7       10        2        4        6        8        9

这是我想要的输出:

> df2
   ID A1 A2 A3 A4 A5 B1 B2 B3 B4 B5 A1.order A2.order A3.order A4.order A5.order B1.order B2.order
1 101  3 NA NA NA  3  3 NA NA  2  2        1        3        5        7       10        2        4
2 102  4  3  1  3  1  2  2  2  3  2        2        4        6        8        9        1        3
3 103  1  1  1  2  2  1  1  3  1  2        1        3        5        7       10        2        4
4 104  3  1  5  1  3  5  4  2  4  2        2        4        6        8        9        1        3
5 105  4  5  4  3  5  1  2  5  5  2        1        3        5        7       10        2        4
6 106  5  3  3  2  4  3  4  4  2  2        2        4        6        8        9        1        3
7 107  3  2  2  1  5  2  5  3  3  2        1        3        5        7       10        2        4
  B3.order B4.order B5.order identical
1        6        8        9      TRUE
2        5        7       10     FALSE
3        6        8        9     FALSE
4        5        7       10     FALSE
5        6        8        9     FALSE
6        5        7       10     FALSE
7        6        8        9     FALSE

【问题讨论】:

  • 你能显示预期的输出吗
  • @akrun 预期输出显示

标签: r dataframe


【解决方案1】:

rle 函数计算向量上的条纹。您可以 (1) 创建一个返回 TRUE/FALSE 的 detect_streaks 函数; (2) 遍历行,检查连续的条纹。

detect_streak <- function(x) {
  streaks <- rle(x)$lengths
  return(any(streaks >= 5))
}

df$identical <- vector(mode = "logical", length = nrow(df))
for (i in 1:nrow(df)) {
  df$identical[i] <- detect_streak(df[i,2:11])
}

在您提供的数据中,A1:B5 之间没有条纹。

【讨论】:

    【解决方案2】:

    根据我对您问题的理解 - 我认为以下代码解决了您的问题。这里的大问题是数据结构 - data.table 有一些很好的重组方法会有所帮助。就像@David 所说的那样,base R rle 将有助于捕获运行条纹

    library(data.table)
    
    running_value = function(input, value){
      run_len = rle(test$input)
      inverse.rle(list(lengths = run_len$lengths,values = run_len$lengths >= value))
    }
    
    setDT(df)
    
    order_dt = df[,c('ID',grep('order', names(df),value = T)), with = F]
    order_dt = melt(order_dt, id.vars = 'ID', value.name = 'order')
    order_dt[,variable := gsub('.order', '', variable)]
    
    response_dt = df[,c(names(df)[!grepl('order',names(df))]), with = F]
    response_dt = melt(response_dt, id.vars = 'ID', value.name = 'input')
    
    order_response = merge(order_dt, response_dt, by = c('ID', 'variable'))
    setorder(order_response, ID, order)
    
    #detailed way to look at it
    order_response[,identical := running_value(input, value = 5), by = c('ID')]
    
    #matching the format you gave
    order_response_sum = order_response[,.(identical = any(identical)), by = c('ID')]
    merge(df, order_response_sum, by = 'ID')
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-04-21
      • 2022-01-22
      • 1970-01-01
      • 2020-10-10
      • 2016-06-26
      • 1970-01-01
      • 2021-07-13
      相关资源
      最近更新 更多