例如,我有一个矩阵k
> k
d e
a 1 3
b 2 4
我想在k
上应用一个函数> apply(k,MARGIN=1,function(p) {p+1})
a b
d 2 3
e 4 5
但是,我还想打印行rowname
的{{1}},以便我可以知道当时该函数应用于哪一行。
看起来像这样:
apply
但我真的不在R中怎么做 有没有人有任何想法?
答案 0 :(得分:12)
这是我认为你问的一个简洁的解决方案。 (为了清楚起见,我调用了输入矩阵mat
而不是k
- 在此示例中,mat
有2列10行,行名为abc1到abc10。)
在下面的代码中,结果out1
是你想要计算的东西(apply命令的结果)。结果out2
与out1
完全相同,只是它打印出它正在处理的rownames(我每行延迟0.3秒,所以你可以看到它确实这样做 - 采取当你希望代码显然全速运行时,这就出来了!)
我提出的技巧是将行号(1到n)绑定到mat
的左侧(创建一个带有一个附加列的矩阵),然后使用它来引用回到rownames mat
。注意行x = y[-1]
,这意味着函数内的实际计算(此处,添加1)忽略第一列行号,这意味着它与out1
的计算相同。无论您想对行执行何种计算,都可以这样做 - 只是假装y
从不存在,并使用x
制定您想要的计算。希望这会有所帮助。
set.seed(1234)
mat = as.matrix(data.frame(x = rpois(10,4), y = rpois(10,4)))
rownames(mat) = paste("abc", 1:nrow(mat), sep="")
out1 = apply(mat,1,function(x) {x+1})
out2 = apply(cbind(seq_len(nrow(mat)),mat),1,
function(y) {
x = y[-1]
cat("Doing row:",rownames(mat)[y[1]],"\n")
Sys.sleep(0.3)
x+1
}
)
identical(out1,out2)
答案 1 :(得分:4)
您可以使用apply调用之外的变量来跟踪行索引并将行名称作为额外参数传递给您的函数:
idx <- 1
apply(k, 1, function(p, rn) {print(rn[idx]); idx <<- idx + 1; p + 1}, rownames(k))
答案 2 :(得分:0)
这应该有效。 cat()
功能是在评估功能期间打印结果时要使用的功能。相反,paste()
只返回一个字符向量,但不会将其发送到命令窗口。
下面的解决方案使用一个作为闭包创建的计数器,允许它“记住”之前运行该函数的次数。请注意使用全局分配<<-
。如果你真的想了解这里发生了什么,我建议你阅读这个wiki https://github.com/hadley/devtools/wiki/
请注意,可能有一种更简单的方法可以做到这一点;我的解决方案假设无法使用apply函数中的典型方法访问当前行的rownumber或rowname。如前所述,这在循环中没有问题。
k <- matrix(c(1,2,3,4),ncol=2)
rownames(k) <- c("a","b")
colnames(k) <- c("d","e")
make.counter <- function(x){
i <- 0
function(){
i <<- i+1
i
}
}
counter1 <- make.counter()
apply(k,MARGIN=1,function(p){
current.row <- rownames(k)[counter1()]
cat(current.row,"\n")
return(p+1)
})
答案 3 :(得分:0)
你不能简单地创建一个新的行名列,然后直接在应用的调用中引用它吗?
答案 4 :(得分:-3)
据我所知,您无法使用apply
执行此操作,但您可以遍历数据框的rownames
。 Lame示例:
lapply(rownames(mtcars), function(x) sprintf('The mpg of %s is %s.', x, mtcars[x, 1]))