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中得到一个错误:行的标识符重复