使用不同的阈值替换多列中的值

时间:2019-05-01 09:06:48

标签: arrays r dataframe

我有一个包含多列的数据集,其中包含要转换为二进制的定量数据。为此,我想对每列使用不同的阈值。

示例

输入:

  antigen1 antigen2 antigen3 antigen4
1      215      421        2       12
2     1524       33      112      443
3      944      836      343       32
4       53      321      563        4

用于生成数据集的代码:

input <- data.frame(
  antigen1 = c(215,1524,944,53),
  antigen2 = c(421, 33, 836,321),
  antigen3 = c(2,112,343,563),
  antigen4 = c(12,443,32,4))

抗原1至抗原4的每列阈值分别为:100、50、400、100

输出:

  antigen1 antigen2 antigen3 antigen4
1        1        1        0        0
2        1        0        0        1
3        1        1        0        0
4        0        1        1        0

这是我使用R尝试过的方法:

# Define lists
cut_offs <- c(100,50,400,100)
antigens <- names(input[1:ncol(input)])

# Loop through both lists
for (anti in antigens) {
  for (co in cut_offs) {
    input[[anti]][input[[anti]]]<cut_offs[co] <- 0 
    input[[anti]][input[[anti]]]>=cut_offs[co] <- 1
  }
}

如何使每个循环后的“ anti”和“ co”同时增加一?

2 个答案:

答案 0 :(得分:2)

我们可以向量化的方式进行此操作,而无需任何循环

+(input >= cut_offs[col(input)])
#      antigen1 antigen2 antigen3 antigen4
#[1,]        1        1        0        0
#[2,]        1        0        0        1
#[3,]        1        1        0        0
#[4,]        0        1        1        0

答案 1 :(得分:1)

我们可以使用mapply

+(mapply(`>=`, input, cut_offs))

#     antigen1 antigen2 antigen3 antigen4
#[1,]        1        1        0        0
#[2,]        1        0        0        1
#[3,]        1        1        0        0
#[4,]        0        1        1        0

如果您需要数据帧作为最终输出,我们可以将其包装在data.frame

data.frame(+(mapply(`>=`, input, cut_offs)))

或与sapply

sapply(seq_along(cut_offs), function(x) +(input[, x] > cut_offs[x]))

就您的for循环而言,您只需要一个循环,因为length(cut_offs)等于input中的列数,因此我们可以使用相同的索引对其进行循环。

temp <- replace(input, TRUE, 0) #Initialise with all values as 0

for (x in seq_along(cut_offs)) {
    temp[input[, x] >= cut_offs[x], x] <- 1 
}

temp
#  antigen1 antigen2 antigen3 antigen4
#1        1        1        0        0
#2        1        0        0        1
#3        1        1        0        0
#4        0        1        1        0