在多个列上嵌套if else语句

use*_*407 7 loops if-statement r dataframe

我有一个大data.frame的前三列包含有关标记的信息.其余列是每个人中该标记的数字类型.每个人都有三列.数据集如下所示:

                      marker alleleA alleleB   X818 X818.1 X818.2   X345 X345.1 X345.2   X346 X346.1 X346.2
1   kgp5209280_chr3_21902067       T       A 0.0000 1.0000 0.0000 1.0000 0.0000 0.0000 0.0000 1.0000 0.0000
2 chr3_21902130_21902131_A_T       A       T 0.8626 0.1356 0.0018 0.7676 0.2170 0.0154 0.8626 0.1356 0.0018
3 chr3_21902134_21902135_T_C       T       C 0.6982 0.2854 0.0164 0.5617 0.3749 0.0634 0.6982 0.2854 0.0164
Run Code Online (Sandbox Code Playgroud)

也就是说,对于每个标记(行),每个个体具有三个值,每列一个.

我想创建一个新的data.frame,它具有与原始行相同的所有行,但每个人只有一列.在每个人的一栏中,我希望每个人的三个值大于0.8.如果没有大于0.8的值,那么我想打印NA.例如,在我为第一行给出的数据集中,我希望第二个值为818(1.0000),第一个值为345(1.0000).在第二行中,我想要第一个值为818(0.8626),而对于345,没有一个值高于0.8,所以我希望NA打印,依此类推.因此,新数据集如下所示:

                     marker alleleA alleleB   X818 X345
1   kgp5209280_chr3_21902067       T       A 1.0000    1
2 chr3_21902130_21902131_A_T       A       T 0.8626   NA
Run Code Online (Sandbox Code Playgroud)

我一直试图使用if/else语句,if [, 4] > 0.8 then [, 4], else...但它似乎没有给我我想要的东西,我也必须循环这个命令,所以它不只是为前三列中的一个人做但对于所有列.

任何帮助,将不胜感激!提前致谢.

Aru*_*run 14

编辑:使用data.table版本> = 1.9.0中实现的快速融合/ dcast方法更新解决方案.去这里获取更多信息.

require(data.table)
require(reshape2)
dt <- as.data.table(df)

# melt data.table
dt.m <- melt(dt, id=c("marker", "alleleA", "alleleB"), 
                 variable.name="id", value.name="val")
dt.m[, id := gsub("\\.[0-9]+$", "", id)] # replace `.[0-9]` with nothing
# aggregation
dt.m <- dt.m[, list(alleleA = alleleA[1], 
         alleleB = alleleB[1], val = max(val)), 
        keyby=list(marker, id)][val <= 0.8, val := NA]
# casting back
dt.c <- dcast.data.table(dt.m, marker + alleleA + alleleB ~ id)
#                        marker alleleA alleleB X345   X346   X818
# 1: chr3_21902130_21902131_A_T       A       T   NA 0.8626 0.8626
# 2: chr3_21902134_21902135_T_C       T       C   NA     NA     NA
# 3:   kgp5209280_chr3_21902067       T       A    1 1.0000 1.0000
Run Code Online (Sandbox Code Playgroud)

解决方案1:可能不是最好的方式,但这是我现在能想到的:

mm <- t(apply(df[-(1:3)], 1, function(x) tapply(x, gl(3,3), max)))
mode(mm) <- "numeric"
mm[mm < 0.8] <- NA 
# you can set the column names of mm here if necessary
out <- cbind(df[, 1:3], mm)

#                       marker alleleA alleleB      1  2      3
# 1   kgp5209280_chr3_21902067       T       A 1.0000  1 1.0000
# 2 chr3_21902130_21902131_A_T       A       T 0.8626 NA 0.8626
# 3 chr3_21902134_21902135_T_C       T       C     NA NA     NA
Run Code Online (Sandbox Code Playgroud)

gl(3,3)给出一个1,1,1,2,2,2,3,3,3含有水平值的因子1,2,3.也就是说,tapplyx一次取值3并获得它们max(前3个,后3个和后3个).并apply逐一发送每一行.


解决方案2:data.table用溶液meltcastdata.table 使用reshapereshape2:

require(data.table)
dt <- data.table(df)
# melt your data.table to long format
dt.melt <- dt[, list(id = names(.SD), val = unlist(.SD)), 
                  by=list(marker, alleleA, alleleB)]
# replace `.[0-9]` with nothing
dt.melt[, id := gsub("\\.[0-9]+$", "", id)]
# get max value grouping by marker and id
dt.melt <- dt.melt[, list(alleleA = alleleA[1], 
                      alleleB = alleleB[1], 
                      val = max(val)), 
        keyby=list(marker, id)][val <= 0.8, val := NA]
# edit mnel (use setattr(,'names') to avoid copy by `names<-` within `setNames`
dt.cast <- dt.melt[, as.list(setattr(val,'names', id)), 
                   by=list(marker, alleleA, alleleB)]

#                        marker alleleA alleleB X345   X346   X818
# 1: chr3_21902130_21902131_A_T       A       T   NA 0.8626 0.8626
# 2: chr3_21902134_21902135_T_C       T       C   NA     NA     NA
# 3:   kgp5209280_chr3_21902067       T       A    1 1.0000 1.0000
Run Code Online (Sandbox Code Playgroud)