如何优化 for 循环以填充数据帧 R



我有一个数据框,我在其中计算一个距离矩阵。

bb=data.frame(Name=paste0('row',1:10),col1=rnorm(10),col2=2*rnorm(10),col3=5*rnorm(10))
dis <- dist(bb[1:nrow(bb),3:ncol(bb)], method = "euclidean")

根据计算的距离矩阵,我创建了一个列表,显示每个点之间的距离。

library(reshape2)
df=melt(as.matrix(dis), varnames = c("row", "col"))

由此,我做了一个循环来提取每个点的比较,并根据值进行归一化。然后,我填充一个数据框,以便将它们全部放在一个源中。

s=NULL
for(i in 1:10){
  w=df[df$row==i&df$col!=i,]
  w=w[order(w$value),]
  w[,3]=(w[,3]-min(w[,3]))/(max(w[,3])-min(w[,3])) # there are a few other computations as well, but not included here for simplicity
  s=rbind(s,w)
}

最后,我希望能够有一个表格,可以在具有这种格式的另一个程序中使用。

> head(s,10)
   row col      value
71   1   8 0.00000000
61   1   7 0.08982679
41   1   5 0.25082060
31   1   4 0.42078163
11   1   2 0.53509305
21   1   3 0.61867437
51   1   6 0.67420271
81   1   9 0.69711889
91   1  10 1.00000000
22   2   3 0.00000000

我的真实数据有3K行和1.2k列,处理时间很慢。有没有更有效的方法对数据帧的某些子集 df 执行计算,这样我最终会得到相同的结果。

我听说 for 循环不应该用于增长数据框,所以我很好奇是否有更有效的方法可以做到这一点。

您可能最好开始以矢量化模式思考。
您正在做的是对涉及同一行上其他值或简单聚合(如 maxmin(的每一行执行操作。

这些包dplyrdata.table帮助您做到这一点。


dplyr

# Take only the rows where col is different from row
df <- filter(.data = df, row != col)
# Group by the col variable, usedto isolate each group
df <- group_by(.data = df, col)
# Create a new var 'value2' with the result of the operation
# Note that min and max refers only to the specific group
df <- mutate(.data = df, value2 = (value-min(value))/(max(value) - min(value)))

dplyr的好处是您可以使用%>%连接这些步骤,其中下一个函数的第一个参数(.data(是最后一个操作的结果:

df %>% 
    filter(row != col) %>% 
    group_by(col) %>% 
    mutate(value2 = (value-min(value))/(max(value) - min(value)))

data.table

df <- data.table(df)
df[row!=col, .(value2 = (value-min(value))/(max(value) - min(value))), by=col]

[请注意,我对data.table不太好,可能有更好的方法可以做到这一点]

最新更新