我有一个数据框,我在其中计算距离矩阵。
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循环不应该用于增长数据框架,所以如果有更有效的方法,我很好奇。
答案 0 :(得分:1)
你可能最好开始考虑矢量化模式
您正在做的是对涉及同一行上其他值的每一行执行操作,或者对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
)是上一个操作的结果: / p>
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
并不是那么好,可能有更好的方法可以做到这一点]