【问题标题】:Aggregating columns聚合列
【发布时间】:2016-03-06 00:40:45
【问题描述】:

我有一个 n 列和 r 行的数据框。我想确定哪一列与第 1 列最相关,然后聚合这两列。聚合列将被视为新列 1。然后,我从集合中删除最相关的列。因此,日期的大小减少了一列。然后我重复这个过程,直到数据框result有n列,第二列是两列的聚合,第三列是三列的聚合,等等。因此我想知道是否有一个有效的或更快的方法来获得我想要的结果。我尝试了各种方法,但到目前为止都没有成功。有什么建议吗?

n <- 5
r <- 6


> df
    X1   X2   X3   X4   X5
1 0.32 0.88 0.12 0.91 0.18
2 0.52 0.61 0.44 0.19 0.65
3 0.84 0.71 0.50 0.67 0.36
4 0.12 0.30 0.72 0.40 0.05
5 0.40 0.62 0.48 0.39 0.95
6 0.55 0.28 0.33 0.81 0.60

result 应该是这样的:

> result
    X1   X2   X3   X4   X5
1 0.32 0.50 1.38 2.29 2.41
2 0.52 1.17 1.78 1.97 2.41
3 0.84 1.20 1.91 2.58 3.08
4 0.12 0.17 0.47 0.87 1.59
5 0.40 1.35 1.97 2.36 2.84
6 0.55 1.15 1.43 2.24 2.57

【问题讨论】:

  • 你分析过你的代码吗?我猜想两次执行cor(temp) 需要一些时间来处理更大的数据。将其分配给一个对象并只进行一次这些计算。此外,cor(temp) 计算所有相关性,但您只需要与第一列的相关性。尝试使用 sapply(temp[,-1], function(x) cor(temp[,1], x) 之类的方法来获取仅与第一列的相关性。
  • @coffeinjunky “个人资料代码”是什么意思?另外,我将如何将您的建议纳入此脚本?我已经尝试在循环中添加它,但我不确定如何添加。
  • 对于分析,参见例如adv-r.had.co.nz/Profiling.html
  • @coffeinjunky 我已经分析了代码,发现瓶颈确实发生在不断计算相关性时。
  • 在这种情况下,请尝试使用which.max(sapply(temp[,-1], function(x) cor(temp[,1], x) ))。它将遍历temp 的每一列并计算与第一列的相关性。现在您正在计算所有可能的相关性(两次),甚至是那些您不关心的相关性。

标签: r


【解决方案1】:

我认为大部分缓慢和最终崩溃来自循环期间的内存开销,而不是相关性(尽管正如@coffeeinjunky 所说,这也可以得到改善)。这很可能是由于在 R 中修改 data.frames 的方式造成的。考虑切换到 data.tables 并利用它们的“通过引用分配”范式。例如,下面是将您的代码翻译成 data.table 语法。您可以对两个循环进行计时、比较性能并评论结果。干杯。

n <- 5L
r <- 6L

result <- setDT(data.frame(matrix(NA,nrow=r,ncol=n)))
temp <- copy(df) # Create a temporary data frame in which I calculate the correlations
set(result, j=1L, value=temp[[1]]) # The first column is the same

for (icol in as.integer(2:n)) {
  mch <- match(c(max(cor(temp)[-1,1])),cor(temp)[,1]) # Determine which are correlated most
  set(x=result, i=NULL, j=as.integer(icol), value=(temp[[1]] + temp[[mch]]))# Aggregate and place result in results datatable
  set(x=temp, i=NULL, j=1L, value=result[[icol]])# Set result as new 1st column
  set(x=temp, i=NULL, j=as.integer(mch), value=NULL) # Remove column
}

【讨论】:

  • 感谢您的回复。我不太确定如何使用数据表。当我尝试您的建议时,我收到以下错误:Error in set(x = result, i = NULL, j = as.integer(icol), value = (temp[[1]] + : RHS of assignment to existing column 'X2' is zero length but not NULL. If you intend to delete the column use NULL. Otherwise, the RHS must have length &gt; 0; e.g., NA_integer_. If you are trying to change the column type to be an empty list column then, as with all column type changes, provide a full length RHS vector such as vector('list',nrow(DT)); i.e., 'plonk' in the new column.
  • @Joseph 是的,我错过了将 &lt;- 转换为 copy() 的过程,这就是应该如何从 data.table 中的 df 创建 temp。如果您正在处理大量数据并且遇到内存/速度问题,那么 data.table 是不可避免的..see this.
  • 谢谢你的提示,我会看看。感谢您的解决方案,效果很好。
【解决方案2】:

试试

for (i in 2:n) {
  maxcor <- names(which.max(sapply(temp[,-1, drop=F], function(x) cor(temp[, 1], x) )))
  result[,i] <- temp[,1] + temp[,maxcor] 
  temp[,1] <- result[,i] # Set result as new 1st column
  temp[,maxcor] <- NULL # Remove column
}

导致错误是因为在最后一次迭代中,子集temp 产生单个向量,并且标准 R 行为是在这种情况下将类从数据帧减少到向量,这导致 sapply 仅传递第一个元素等。

还有一条评论:目前,您使用的是最正相关,而不是最强相关,也可能是负相关。确保这是您想要的。


在评论中解决您的问题:请注意,可以通过避免重复计算来改进您的旧代码。例如,

   mch <- match(c(max(cor(temp)[-1,1])),cor(temp)[,1])

包含两次命令cor(temp)。这意味着每个相关性都计算了两次。替换为

  cortemp <- cor(temp)
  mch <- match(c(max(cortemp[-1,1])),cortemp[,1])

应该将初始代码行的计算负担减半。

【讨论】:

  • 非常感谢您的努力。这完美地工作。还有一件事:你说'将它分配给一个对象并只进行一次这些计算。你是什​​么意思?它不是已经分配给一个对象(temp)吗?如果没有,我该怎么做才能让它运行得更快?
  • 关于相关性:所有值都将高于 0,所以这应该不是问题,对吧?
  • 啊,是的,我明白你的意思了。谢谢你的澄清。在您的解决方案中,您已经解决了这个问题,对吗?
  • 是的,我的解决方案避免了两次计算它们,并且避免了计算与您不感兴趣的列之间的相关性。
  • 非常感谢您的帮助和时间。您的解决方案对我帮助很大,并且使处理速度更快。
猜你喜欢
  • 2023-01-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-10
相关资源
最近更新 更多