2012-06-08 76 views
4

例如,我有一个矩阵k如何在R中使用apply时打印当前行的名称?

> 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 

不过,我也想打印的行的rownameapply让我能知道当时该函数应用于哪一行。

它可能看起来像这样:

apply(k,MARGIN=1,function(p) {print(rowname(p)); p+1}) 

但我真的不办怎么办,在河 有没有人有什么想法?

+0

你能澄清你期待的答案吗?如果你在'k'的第一个实例中给每个数字加1,那么你在第二个'k'实例中没有得到答案。 – ChrisW

+1

只是使用for循环。 – joran

+0

这里有很多非常混乱的建议 - 如果我提出的解决方案能够满足您的要求,您可以告诉我吗? –

回答

-3

据我所知,你不能用apply这样做,但你可以通过你的数据框的rownames循环。跛脚例如:

lapply(rownames(mtcars), function(x) sprintf('The mpg of %s is %s.', x, mtcars[x, 1])) 
+0

你可以用'apply'来完成它 - 不仅循环通常是一个非常糟糕的主意,而且上面的例子实际上并不是一个接一个地打印它们(放入一个Sys.sleep()延迟,你会看到它们都在最后一次爆发出来)... –

+0

@TimP - 'flush.console()'这样的方式很方便 – Chase

+0

@TimP在他的回答中证明,这可以通过apply()来实现。这个被接受的答案是误导性的。 – Rhubarb

0

这应该工作。在评估函数期间打印结果时,您想要使用的功能是cat()。相反,paste()只是返回一个字符矢量,但不会将它发送到命令窗口。

下面的解决方案使用一个创建为闭包的计数器,允许它“记住”该函数之前运行过多少次。请注意使用全局分配<<-。如果你真的想知道这里发生了什么,我推荐阅读这个wiki https://github.com/hadley/devtools/wiki/

请注意可能有一个更简单的方法来做到这一点;我的解决方案假设无法使用应用函数中的典型方法访问当前行的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) 
}) 
4

您可以使用一个变量的应用调用的外部跟踪行索引的,并通过该行的名称作为一个额外的参数传递给你的函数:

idx <- 1 
apply(k, 1, function(p, rn) {print(rn[idx]); idx <<- idx + 1; p + 1}, rownames(k)) 
+0

它的工作原理!但它仍然需要使用全局变量作为计数器..不是很优雅.. –

+0

如果允许使用全局变量,这很容易,但我上面的解决方案不需要这些(假设我已经正确理解了任务):) –

+0

这与在for循环中使用循环变量没有什么不同。它不亚于此。 – ALiX

12

这里有一个巧妙的解决办法是什么我想你在问。 (我称为输入矩阵mat而非k为清楚起见 - 在这个例子中,具有mat 2列和10行,并且行是通过命名ABC1到abc10。)

在下面的代码,结果out1是你想要计算的东西(apply命令的结果)。 out2的结果与out1完全相同,不同之处在于它打印出了正在处理的rownames(我将每行延迟0.3秒,因此您可以看到它确实可以做到这一点 - 当您希望代码运行全速显然!)

我想出的技巧是将行号(1到n)放在mat(创建一个额外的列的矩阵)的左侧,然后用它来回引用到mat的rownames。注意行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

接受的答案是错误和误导的。这应该是被接受的答案。 – Rhubarb

0

难道你不能简单地创建一个新的行名称列,然后直接在调用中引用它应用?

相关问题