根据列中的唯一值将数据框转换为 "ranked lists" 的矩阵
Convert data frame into a matrix of "ranked lists" based on unique values in column
假设我有一个如下所示的数据框 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
我想最终将其转换为 "ranked lists" 的矩阵,其行具有 entry
列中的唯一值,列数应等于 给定 entry
的 point
列中唯一元素的最大 数量。在此示例中,它将是 3。每一行应使用 point
列中的相应值填充,并根据 value
中的相应元素降序排序(例如,行 A
应具有v2
作为第一列中的值)。如果 entry
比矩阵中的列数少 points
,则该行的其余部分应填充 NAs
。
所以,预期的输出应该是这样的:
>df
1 2 3
A v2 v1 NA
B v3 v1 NA
C v4 NA NA
D v2 v3 v4
E v2 NA NA
到目前为止,我已经尝试使用
创建某种应急措施table
with(df, table(df$point, df$entry))
但当然我的实际数据是数百万条目的顺序,即使在子集为 100 entries
和数百个独特的 points
.我也试过
xtabs(~ entry + point, data=df)
在我的真实数据上得到相同的结果。接下来,我尝试使用
将其拆分为有序列表
df = split(df$point, df$entry)
工作正常而且速度足够快,buuuuut.. 现在我在将它转换为结果矩阵时遇到问题。大概是这样
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
考虑使用 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
假设我有一个如下所示的数据框 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
我想最终将其转换为 "ranked lists" 的矩阵,其行具有 entry
列中的唯一值,列数应等于 给定 entry
的 point
列中唯一元素的最大 数量。在此示例中,它将是 3。每一行应使用 point
列中的相应值填充,并根据 value
中的相应元素降序排序(例如,行 A
应具有v2
作为第一列中的值)。如果 entry
比矩阵中的列数少 points
,则该行的其余部分应填充 NAs
。
所以,预期的输出应该是这样的:
>df
1 2 3
A v2 v1 NA
B v3 v1 NA
C v4 NA NA
D v2 v3 v4
E v2 NA NA
到目前为止,我已经尝试使用
创建某种应急措施tablewith(df, table(df$point, df$entry))
但当然我的实际数据是数百万条目的顺序,即使在子集为 100 entries
和数百个独特的 points
.我也试过
xtabs(~ entry + point, data=df)
在我的真实数据上得到相同的结果。接下来,我尝试使用
将其拆分为有序列表df = split(df$point, df$entry)
工作正常而且速度足够快,buuuuut.. 现在我在将它转换为结果矩阵时遇到问题。大概是这样
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
考虑使用 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