【问题标题】:How to find three consecutive rows with the same value如何找到具有相同值的三个连续行
【发布时间】:2015-12-13 10:57:30
【问题描述】:

我有一个如下的数据框:

chr     leftPos    Sample1  X.DD   3_samples    MyStuff
1        324         -1        1        1           1
1        4565        -1        0        0           0 
1        6887        -1        1        0           0
1        12098        1       -1        1           1
2        12          -1        1        0           1
2        43          -1        1        1           1
5        1           -1        1        1           0
5        43           0        1       -1           0
5        6554         1        1        1           1
5        7654        -1        0        0           0
5        8765         1        1        1           0
5        9833         1        1        1          -1
6        12           1        1        0           0
6        43           0        0        0           0
6        56           1        0        0           0
6        79           1        0       -1           0
6        767          1        0       -1           0
6        3233         1        0       -1           0

我想按照以下规则进行转换 对于每条染色体:

一个。如果一列中连续出现三个或更多 1 或 -1,则该值保持原样。

b.如果一列中连续的 1 或 -1 少于三个,则 1 或 -1 的值变为 0

列中的行必须具有相同的符号(+ 或 -ve)才能称为连续。

上面dataframe的结果应该是:

chr     leftPos    Sample1  X.DD   3_samples    MyStuff
    1        324         -1        0        0           0
    1        4565        -1        0        0           0 
    1        6887        -1        0        0           0
    1        12098        0        0        0           0
    2        12           0        0        0           0
    2        43           0        0        0           0
    5        1            0        1        0           0
    5        43           0        1        0           0
    5        6554         0        1        0           0
    5        7654         0        0        0           0
    5        8765         0        0        0           0
    5        9833         0        0        0           0
    6        12           0        0        0           0
    6        43           0        0        0           0
    6        56           1        0        0           0
    6        79           1        0       -1           0
    6        767          1        0       -1           0
    6        3233         1        0       -1           0

我已经设法连续两行执行此操作,但我不确定如何更改三行或更多行。

DAT_list2res <-cbind(DAT_list2[1:2],DAT_list2res)
colnames(DAT_list2res)[1:2]<-c("chr","leftPos")
DAT_list2res$chr<-as.numeric(gsub("chr","",DAT_list2res$chr))
DAT_list2res<-as.data.frame(DAT_list2res)
dx<-DAT_list2res
f0 <- function( colNr, dx)
{
  col <- dx[,colNr]
  n1 <- which(col == 1| col == -1)          # The `1`-rows.
  d0 <- which( diff(col) == 0)      # Consecutive rows in a column are equal.
  dc0 <- which( diff(dx[,1]) == 0)  # Same chromosome.
  m <- intersect( n1-1, intersect( d0, dc0 ) )
  return ( setdiff( 1:nrow(dx), union(m,m+1) ) )
}
g <- function( dx )
{
  for ( i in 3:ncol(dx) ) { dx[f0(i,dx),i] <- 0 }  
  return ( dx )
}
dx<-g(dx)

【问题讨论】:

    标签: r


    【解决方案1】:

    这是一种仅使用基址R 的解决方案。

    首先定义一个函数,它将替换任何小于 3 的重复为零:

    replace_f <- function(x){
      subs <- rle(x)
      subs$values[subs$lengths < 3] <- 0
      inverse.rle(subs)
    }
    

    然后将您的data.frame 拆分为chr,然后将该函数应用于您要更改的所有列(在本例中为第 3 到 6 列):

    df[,3:6] <- do.call("rbind", lapply(split(df[,3:6], df$chr), function(x) apply(x, 2, replace_f)))
    

    请注意,我们在替换原始数据之前将结果与rbind 结合在一起。这将为您提供所需的结果:

       chr leftPos Sample1 X.DD X3_samples MyStuff
    1    1     324      -1    0          0       0
    2    1    4565      -1    0          0       0
    3    1    6887      -1    0          0       0
    4    1   12098       0    0          0       0
    5    2      12       0    0          0       0
    6    2      43       0    0          0       0
    7    5       1       0    1          0       0
    8    5      43       0    1          0       0
    9    5    6554       0    1          0       0
    10   5    7654       0    0          0       0
    11   5    8765       0    0          0       0
    12   5    9833       0    0          0       0
    13   6      12       0    0          0       0
    14   6      43       0    0          0       0
    15   6      56       1    0          0       0
    16   6      79       1    0         -1       0
    17   6     767       1    0         -1       0
    18   6    3233       1    0         -1       0
    

    【讨论】:

      【解决方案2】:

      使用rleiddata.table 解决方案将是

      require(data.table)
      setDT(dat)
      dat[,Sample1 := Sample1 * as.integer(.N>=3), by=.(chr, rleid(Sample1))]
      

      这使用了rleid(Sample1)data.table 的有用.N-variable 的分组。

      对所有列执行此操作,您可以使用eval(parse(text=...)) 语法,如下所示:

      for(i in names(dat)[3:6]){
        by_string = paste0("list(chr, rleid(", i, "))")
        def_string = paste0(i, "* as.integer(.N>=3)")
        dat[,(i) := eval(parse(text=def_string)), by=eval(parse(text=by_string))]
      }
      

      所以结果是:

      > dat[]
          chr leftPos Sample1 X.DD X3_samples MyStuff
       1:   1     324      -1    0          0       0
       2:   1    4565      -1    0          0       0
       3:   1    6887      -1    0          0       0
       4:   1   12098       0    0          0       0
       5:   2      12       0    0          0       0
       6:   2      43       0    0          0       0
       7:   5       1       0    1          0       0
       8:   5      43       0    1          0       0
       9:   5    6554       0    1          0       0
      10:   5    7654       0    0          0       0
      11:   5    8765       0    0          0       0
      12:   5    9833       0    0          0       0
      13:   6      12       0    0          0       0
      14:   6      43       0    0          0       0
      15:   6      56       1    0          0       0
      16:   6      79       1    0         -1       0
      17:   6     767       1    0         -1       0
      18:   6    3233       1    0         -1       0
      

      【讨论】:

      • 可能data.table解决方案,OP不必必须使用eval(parse(text=...))可以.
      • @DavidArenburg 我认为也使用rle 会很无聊。没有eval(parse(text=...))怎么办?
      • 你想不出别的办法,不代表没有。您的解决方案可能很好,我只是不明白“这样做”、“这是唯一的方法”、“这是 x 封装方式”等,因为可能有 no 其他选择。例如,一种替代方案可能是setDT(df)[,names(df)[3:6] := lapply(.SD, function(x) ave(x, rleid(x), FUN = function(x) (length(x) &gt; 2) * x)), .SDcols = 3:6, by = chr],但我怀疑任何人都将击败上述基本解决方案。
      • @DavidArenburg 好吧,我错过了沟通。我的第一句“使用rleiddata.table 解决方案将是”使用“A”而不是“The”和连词“would”的原因正是为了表达我的解决方案是众多解决方案之一。正如你所指出的那样。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-21
      • 1970-01-01
      • 2018-12-16
      • 1970-01-01
      • 2019-03-20
      相关资源
      最近更新 更多