根据另一列

时间:2017-08-14 20:58:46

标签: r dataframe data.table

我实际上正在处理基因组数据,我有一个数据框,我将向您展示前三行(见下表):

Chrom |   POS    |     ID      | REF | ALT | HapA | HapB |
----------------------------------------------------------
 22   | 16495833 | rs116911124 |  A  |  C  |   1  |  0   |
 22   | 19873357 | rs116378360 |  T  |  A  |   0  |  1   |
 22   | 21416404 | rs117982183 |  T  |  T  |   0  |  .   |

所以,我想替换" 0"," 1"的值。和"。"来自" HapA"和" HapB"根据REF和ALT列的列,用于数据框中的每一行。例如:

a)对于第一行我想改变" 1"在HapA专栏中为" C"在ALT列中," 0"在" A"的HapB列中; REF栏中的值

b)对于第二行改变" 0"对于" T"在" REF"列和" 1"对于" A"在" ALT"列。

c)最后,对于"。"将其更改为" NA"

我认为这可以通过" if else"来实现。或者使用data.table。

非常感谢。

3 个答案:

答案 0 :(得分:0)

我认为if_else()recode()case_when()都可以为此工作。在这里,我尝试使用mutate_at()将功能应用于HapA和HapB。如果这些列中的一个值不等于1,0,或者。那么函数应该将值作为字符串返回。

mutate_at(df, vars(HapA, HapB),
    function(x) {case_when(x == 1 ~ .$ALT,
                     x == 0 ~ .$REF,
                     x == . ~ NA_character_,
                     TRUE ~ as.character(x)) } )

答案 1 :(得分:0)

有点不清楚你想要什么,因为你没有指定0列第三行HapA应该发生什么,但考虑到你是什么说,这是一个dplyr解决方案:

library(dplyr)

df <- read.table(text = "
'Chrom'     'POS'      'ID'       'REF'  'ALT' 'HapA' 'HapB'
22     16495833   'rs116911124'    'A'     'C'      1     0  
22     19873357   'rs116378360'    'T'     'A'      0     1  
22     21416404   'rs117982183'    'T'     'T'      0     .", header = T, stringsAsFactors = F)

df %>%
  mutate(HapA = ifelse(HapA == 1, ALT, ifelse(HapA == 0, REF, NA)),
         HapB = ifelse(HapB == 1, ALT, ifelse(HapB == 0, REF, NA)))

##   Chrom      POS          ID REF ALT HapA HapB
## 1    22 16495833 rs116911124   A   C    C    A
## 2    22 19873357 rs116378360   T   A    T    A
## 3    22 21416404 rs117982183   T   T    T <NA>

答案 2 :(得分:0)

这不是一个真正的问题,但我会猜测它是什么:

  

如何按照以下规则替换HapAHapB的值:

     
      
  1. 如果"0",则替换为REF
  2. 的值   
  3. 如果"1",则替换为ALT
  4. 的值   
  5. 如果".",则替换为NA
  6.   

请注意,我还假设HapAHapB是字符列,因为.不能是数字值。

如果这是正确的解释,那么就不需要使用花哨的技巧。这是一个&#34; if-else&#34;问题。这是使用data.table的解决方案,我认为这在基因组分析中很常见。首先,我将创建示例数据集:

library(data.table)

dt <- fread(
  header = TRUE,
  colClasses = c(
    Chrom = "character",
    POS   = "integer",
    ID    = "character",
    REF   = "character",
    ALT   = "character",
    HapA  = "character",
    HapB  = "character"
  ),
  input = "
Chrom  POS        ID               REF     ALT      HapA HapB
22     16495833   'rs116911124'    'A'     'C'      1     0  
22     19873357   'rs116378360'    'T'     'A'      0     1  
22     21416404   'rs117982183'    'T'     'T'      0     ."
)
dt
#    Chrom      POS            ID REF ALT HapA HapB
# 1:    22 16495833 'rs116911124' 'A' 'C'    1    0
# 2:    22 19873357 'rs116378360' 'T' 'A'    0    1
# 3:    22 21416404 'rs117982183' 'T' 'T'    0    .

这是很长的一部分。这是短篇小说。

dt[HapA == "0", HapA := REF]
dt[HapA == "1", HapA := ALT]
dt[HapA == ".", HapA := NA]
dt[HapB == "0", HapB := REF]
dt[HapB == "1", HapB := ALT]
dt[HapB == ".", HapB := NA]
dt
#    Chrom      POS            ID REF ALT HapA HapB
# 1:    22 16495833 'rs116911124' 'A' 'C'  'C'  'A'
# 2:    22 19873357 'rs116378360' 'T' 'A'  'T'  'A'
# 3:    22 21416404 'rs117982183' 'T' 'T'  'T'   NA

强烈建议以一种简单的方式写出来,如上所述。它简短,几乎没有重复,一眼就能轻松理解。但是,如果您想将此概括为大量列,则需要编写大量重复行。所以这是一个循环版本:

replaced_columns <- c("HapA", "HapB")  # Switch these out for any
source_columns   <- c("REF", "ALT")    # number of columns

for (rr in replaced_columns) {
  for (source_i in seq_along(source_columns)) {
    target_rows <- which(dt[[rr]] == source_i - 1)
    dt[
      target_rows,
      (rr) := .SD,
      .SDcols = source_columns[source_i]
    ]
  }
}

dt
#    Chrom      POS            ID REF ALT HapA HapB
# 1:    22 16495833 'rs116911124' 'A' 'C'  'C'  'A'
# 2:    22 19873357 'rs116378360' 'T' 'A'  'T'  'A'
# 3:    22 21416404 'rs117982183' 'T' 'T'  'T'    .