我有一个数据框,我在其中计算一个距离矩阵。
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 循环不应该用于增长数据框,所以我很好奇是否有更有效的方法可以做到这一点。
您可能最好开始以矢量化模式思考。
您正在做的是对涉及同一行上其他值或简单聚合(如 max
和 min
(的每一行执行操作。
这些包dplyr
或data.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
不太好,可能有更好的方法可以做到这一点]