R 将数据帧转换为矩阵;排名名单“;基于列中的唯一值

R 将数据帧转换为矩阵;排名名单“;基于列中的唯一值,r,dataframe,matrix,ranking,R,Dataframe,Matrix,Ranking,假设我有一个数据帧df,看起来像这样: df = data.frame(c("A", "A", "B", "B", "C", "D", "D", "D", "E"), c(0.1, 0.3, 0.1, 0.8, 0.4, 0.7, 0.5, 0.2, 0.1), c("v1", "v2", "v1", "v3", "v4", "v2", "v3", "v4", "v2")) colnames(df) = c("entry", "value", "point")

假设我有一个数据帧
df
,看起来像这样:

df = data.frame(c("A", "A", "B", "B", "C", "D", "D", "D", "E"), 
        c(0.1, 0.3, 0.1, 0.8, 0.4, 0.7, 0.5, 0.2, 0.1),
        c("v1", "v2", "v1", "v3", "v4", "v2", "v3", "v4", "v2"))

colnames(df) = c("entry", "value", "point")
df = df[order(df$entry, -df$value),]

df
   entry value point
2     A   0.3    v2
1     A   0.1    v1
4     B   0.8    v3
3     B   0.1    v1
5     C   0.4    v4
6     D   0.7    v2
7     D   0.5    v3
8     D   0.2    v4
9     E   0.1    v2
>df
   1   2   3  
A  v2  v1  NA 
B  v3  v1  NA 
C  v4  NA  NA 
D  v2  v3  v4
E  v2  NA  NA
我希望最终将其转换为一个“排名列表”矩阵,该矩阵将
条目
列中的唯一值作为行,列数应等于给定
条目
列中唯一元素的最大数。在这个例子中是3。每一行都应填充
列中的相应值,并根据
中的相应元素进行向下排序(例如,行
A
应将
v2
作为第一列中的值)。如果
条目
点数
少于矩阵中的列数,则行的其余部分应填充
NAs

因此,预期输出应该如下所示:

df = data.frame(c("A", "A", "B", "B", "C", "D", "D", "D", "E"), 
        c(0.1, 0.3, 0.1, 0.8, 0.4, 0.7, 0.5, 0.2, 0.1),
        c("v1", "v2", "v1", "v3", "v4", "v2", "v3", "v4", "v2"))

colnames(df) = c("entry", "value", "point")
df = df[order(df$entry, -df$value),]

df
   entry value point
2     A   0.3    v2
1     A   0.1    v1
4     B   0.8    v3
3     B   0.1    v1
5     C   0.4    v4
6     D   0.7    v2
7     D   0.5    v3
8     D   0.2    v4
9     E   0.1    v2
>df
   1   2   3  
A  v2  v1  NA 
B  v3  v1  NA 
C  v4  NA  NA 
D  v2  v3  v4
E  v2  NA  NA
到目前为止,我已经尝试使用

with(df, table(df$point, df$entry))
但当然,我的实际数据是以数百万条条目的顺序排列的,而且上面的命令会增加大量的RAM,即使是将100条
条目
与数百个唯一的
进行子集设置时也是如此。我也试过了

xtabs(~ entry + point, data=df)
在我的真实数据上也有同样的结果。接下来,我尝试使用

df = split(df$point, df$entry)
这很好,速度也很快,Buuuuuut。。现在我无法将其转换为结果矩阵。大概是这样的

matrix(sapply(df, function(x) unlist(x)), nrow=length(df), ncol=max(sapply(df, length)))
或者先初始化一个矩阵,然后执行一些
rbind
之类的操作

res = matrix(NA, nrow=length(df), ncol=max(sapply(df, length)))
rownames(res) = names(df)
....

你能帮我吗?

dplyr

df %>% 
   group_by(entry) %>% 
   mutate(unq=rank(rev(value))) %>% 
   select(-value) %>% 
   tidyr::spread(unq,point)
# A tibble: 5 x 4
# Groups:   entry [5]
  entry `1`   `2`   `3`  
  <fct> <fct> <fct> <fct>
1 A     v2    v1    NA   
2 B     v3    v1    NA   
3 C     v4    NA    NA   
4 D     v2    v3    v4   
5 E     v2    NA    NA   
df%>%
分组依据(条目)%>%
变异(unq=等级(修订(值)))%>%
选择(-value)%%>%
tidyr::价差(unq,点)
#一个tibble:5x4
#分组:条目[5]
条目'1``2``3`
1 A v2 v1 NA
2bv3v1na
3 C v4 NA
4d v2 v3 v4
5 E v2 NA

带有
dplyr

df %>% 
   group_by(entry) %>% 
   mutate(unq=rank(rev(value))) %>% 
   select(-value) %>% 
   tidyr::spread(unq,point)
# A tibble: 5 x 4
# Groups:   entry [5]
  entry `1`   `2`   `3`  
  <fct> <fct> <fct> <fct>
1 A     v2    v1    NA   
2 B     v3    v1    NA   
3 C     v4    NA    NA   
4 D     v2    v3    v4   
5 E     v2    NA    NA   
df%>%
分组依据(条目)%>%
变异(unq=等级(修订(值)))%>%
选择(-value)%%>%
tidyr::价差(unq,点)
#一个tibble:5x4
#分组:条目[5]
条目'1``2``3`
1 A v2 v1 NA
2bv3v1na
3 C v4 NA
4d v2 v3 v4
5 E v2 NA

考虑使用
by
按条目分割并构建所需的向量。对于最终矩阵中相同长度的行,根据需要添加
NA
,其中下面的
3
可以更改为所需的列数

vec_list <- by(df, df$entry, function(sub) {
    vec <- as.character(sub[order(-sub$value),]$point)    
    c(vec, rep(NA, 3 - length(vec)))    
})

final_matrix <- do.call(rbind, vec_list)

final_matrix
#   [,1] [,2] [,3]
# A "v2" "v1" NA  
# B "v3" "v1" NA  
# C "v4" NA   NA  
# D "v2" "v3" "v4"
# E "v2" NA   NA 

vec\u list考虑使用
by
按条目拆分并构建所需的向量。对于最终矩阵中相同长度的行,根据需要添加
NA
,其中下面的
3
可以更改为所需的列数

vec_list <- by(df, df$entry, function(sub) {
    vec <- as.character(sub[order(-sub$value),]$point)    
    c(vec, rep(NA, 3 - length(vec)))    
})

final_matrix <- do.call(rbind, vec_list)

final_matrix
#   [,1] [,2] [,3]
# A "v2" "v1" NA  
# B "v3" "v1" NA  
# C "v4" NA   NA  
# D "v2" "v3" "v4"
# E "v2" NA   NA 

vec\u list似乎可以做到这一点:,例如
dcast(df,entry~rowid(entry),value.var=“point”)
@Henrik它就是沿着这些路线走的,但是
restrape
的问题是它将所有唯一的
值作为列保存,而不是给定
条目的最大元素数。此外,它们没有分类。如果你看一下预期的输出,也许它是清晰的。至少对于文章中提供的例子,我的建议给出了预期的输出。很抱歉,我忘记了
库(data.table)
setDT(df)
之前的
dcast
@Henrik:它真的没有。它产生(仅第一行作为示例):
入口点。0.3点。0.1点。0.8点。0.4点。0.7点。0.5点。0.2
2A v2 v1
它应该仅是
A v2 v1 NA
。。不是7列,但谢谢你的建议忘了提及(再次…):我从你的排序数据开始。(如果您使用
setDT
dcast
,您也可以使用
setorder(df,entry,-value)
)对其进行排序。似乎这样可以做到:,例如
dcast(df,entry~rowid(entry),value.var=“point”)
@Henrik它就是沿着这些路线,但是
重塑
的问题在于,它将所有唯一的
s保留为列,而不是给定
条目
的最大元素数。此外,它们没有分类。如果你看一下预期的输出,也许它是清晰的。至少对于文章中提供的例子,我的建议给出了预期的输出。很抱歉,我忘记了
库(data.table)
setDT(df)
之前的
dcast
@Henrik:它真的没有。它产生(仅第一行作为示例):
入口点。0.3点。0.1点。0.8点。0.4点。0.7点。0.5点。0.2
2A v2 v1
它应该仅是
A v2 v1 NA
。。不是7列,但谢谢你的建议忘了提及(再次…):我从你的排序数据开始。(如果您使用
setDT
dcast
,您也可以使用
setorder(df,entry,-value)
)对其进行排序。完美:]您可以补充一下,它需要
spread
功能的
tidyr
包。谢谢大家的帮助是的,忘了它只是提醒一下:如果您的数据帧中有数百万个条目,您很可能会从
tidyr::spread
函数中得到一个
错误:行的标识符重复
,该函数最终将迫使您通过
tibble::rowid_to_column()分配新的行ID
作为上述命令的第二行。。问题是已知的,但尚未解决:]您是否可以补充一点,即它需要
tidyr
软件包来实现
spread
功能。谢谢大家的帮助是的,忘了它只是提醒一下:如果您的数据框中有数百万个条目,您很可能会从
tidyr::spread中得到一个
错误:行的标识符重复