使用R有条件地替换数据帧中的列值

时间:2014-10-03 15:54:52

标签: r replace

让我们制作一个虚拟数据集

ll = data.frame(rbind(c(2,3,5), c(3,4,6), c(9,4,9)))
colnames(ll)<-c("b", "c", "a")
> ll
  b c a
1 2 3 5
2 3 4 6
3 9 4 9

P = data.frame(cbind(c(3,5), c(4,6), c(8,7)))
colnames(P)<-c("a", "b", "c")
> P
  a b c
1 3 4 8
2 5 6 7

我想创建一个新的数据帧,当ll的每列中的值小于a,b和&amp;的相应值时,它将变为0。 c在P的第一行;换句话说,我想看看

> new_ll
  b c a
1 0 0 5
2 0 0 6
3 9 0 9

所以我这样尝试了

nn=c("a", "b", "c")
new_ll = sapply(nn, function(i) 
  ll[,paste0(i)][ll[,paste0(i)] < P[,paste0(i)][1]] <- 0)

但由于某种原因它不起作用!我必须在我的剧本中犯一个愚蠢的错误!!有什么想法吗?

> new_ll
a b c 
0 0 0 

3 个答案:

答案 0 :(得分:1)

您可以在ll中找到小于P的第一行apply的值:

t(apply(ll, 1, function(x) x<P[1,][colnames(ll)]))
      [,1] [,2]  [,3]
[1,]  TRUE TRUE FALSE
[2,]  TRUE TRUE FALSE
[3,] FALSE TRUE FALSE

此处,P的第一行被排序以匹配ll,然后比较元素。

感谢Ananda Mahto认识到apply不是必需的:

ll < c(P[1, names(ll)])
         b    c     a
[1,]  TRUE TRUE FALSE
[2,]  TRUE TRUE FALSE
[3,] FALSE TRUE FALSE

TRUE值显示您要用0替换的位置:

ll[ ll < c(P[1, names(ll)]) ] <- 0
ll
  b c a
1 0 0 5
2 0 0 6
3 9 0 9

要修复代码,您需要以下内容:

do.call(cbind, lapply(names(ll), function(i) {
    ll[,i][ll[,i] < P[,i][1]] <- 0
    return(ll[i])}))
  b c a
1 0 0 5
2 0 0 6
3 9 0 9

改变了什么?首先,sapply更改为lapply,函数返回每次迭代的向量。其次,名称按预期结果的正确顺序显示。第三,将结果与cbind放在一起以得到最终矩阵。作为奖励,已删除对paste0的多余调用。

答案 1 :(得分:0)

您也可以尝试mapply,它将函数应用于每个相应的元素。在此,llP都是data.frames。因此,它应用每列的功能并进行回收。在这里,我将column names的{​​{1}}与P的{​​{1}}匹配(类似于@Matthew Lundberg),并查找每列中ll的哪些元素为ll比相应的列(<的一行被回收)并返回一个逻辑索引。然后将匹配逻辑条件的元素分配给P

0

答案 2 :(得分:0)

如果您知道llP是数字,那么您也可以将其作为

llm <- as.matrix(ll)
pv <- as.numeric(P[1, colnames(llm)])  
llm[sweep(llm, 2, pv, `<=`)] <- 0
data.frame(llm)
#   b c a
# 1 0 0 5
# 2 0 0 6
# 3 9 0 9