R:5列中一列的随机值
R: Random values from one column in 5 columns
我有一个包含大约 100 个足球运动员号码的数据框 (df
)(如果有更多的球员注册,这个数字会增加)。每个 player_number
由 6 位数字组成(例如 178530)。
每个玩家都要评论5个其他玩家,所以最终所有玩家都会被另外5个评论。因此我想给每个 player_number
随机分配 5 个不同的玩家号码(来自 player_number
列)。为避免将评论分配给自己 and/or 玩家必须对同一玩家进行两次(或更多次)评论,每个 player_number
应该在每一列和每一行中只出现一次。 数据框应如下所示:
player_number review1 review2 review3 review4 review5
178530 207145 655600 443274 604060 804226
245678 947821 214525 332324 174589 868954
…
玩家178530需要审核玩家207145、655600等
对于 review1 列,我使用了:
set.seed(1)
df$review1 <- sample(df$player_number, nrow(df), replace=F)
这适用于 review1
,但将其应用于其他评论列会导致在多行中重复 player_number
。谁能帮助我,让每个 player_number
在每一列和每一行中只出现一次?提前致谢。
编辑:在之前的版本中我简化了 player_number 太多 (1:100)
您可以为此编写一个函数。这个想法是获取 100 个 ID 或玩家号码的向量;随机抽取 5 个 unique 起始值作为 5 个新向量的起始值并绑定它们以获得您的结果,其中在每一行和每一列中都没有找到超过一次的 ID。
例如,如果您有数字1到5(那个顺序),并且想将其中的3个数字分配给1到5的每个数字;在一行或一列中没有数字超过一次。
1 3 2 5
2 4 3 1
3 5 4 2
4 1 5 3
5 2 1 4
这是执行此操作的函数。
play <- function(v, i){
starts <- sample(2:length(v), i, replace=F)
v2 <- v
for(m in 1:i){
v2 <- cbind(v2, c(v[starts[m]:length(v)], v[0:(starts[m]-1)]) )
}
colnames(v2) <- c('id', paste0('R', 1:i))
return(v2)
}
试试吧。
play(1:5, 3)
这是一个类似的函数,它接受一个数据框,因为你在问题中要求它。
playDF <- function(df, i){
starts <- sample(1:nrow(df), i+1, replace=F)
sq2 <- NULL
for(m in 1:(i+1)){
sq2 <- cbind(sq2, c(df[starts[m]:nrow(df),], df[0:(starts[m]-1),]) )
}
sq2 <- as.data.frame(sq2)
colnames(sq2) <- c('player_number', paste0('review', 1:(i)))
return(sq2)
}
我已经为您的问题添加了示例数据。 运行 函数并将其应用于数据。
df <- data.frame(player_number=c(sample(111111:999999, 100, replace=F)))
playDF(df, 5)
可能不是最有效的,但这是一个仅使用基数 R 的解决方案。在这里,我一次只从 1:100 的向量中抽取 1 个数字,当前向量中没有已经存在的数字行和当前列。
对于第 100 行,这意味着数字是从长度为 1 的向量中采样的,这导致 sample
函数的行为不同。因此,为了防止这种意外行为,我好心地从 Sampling in R from vector of varying length 中授予了 sample.vec
自定义函数。
df <- data.frame(player_number = c(1:100))
df <- cbind(df, matrix(NA, 100, 5))
sample.vec <- function(x, ...) x[sample(length(x), ...)]
for(i in 1:100){
for(j in 2:6){
df[i,j] <- sample.vec(setdiff(c(1:100),c(df[i,], df[,j])), 1)
}
}
问题更改后的更新:如果您想使用那些 6 位数的自定义玩家号码,一个选项可以是将所有列转换为因子,使用 1:100 作为级别,使用实际玩家号码作为标签。所以在上面的代码之后,你可以做这样的事情:
set.seed(1); player_number = sort(sample(100000:999999, 100)) # in your data, just create this vector beforehand using the actual player numbers
df[] <- lapply(df, function(x) {factor(x, levels = c(1:100), labels = player_number)})
证明:
head(df)
player_number 1 2 3 4 5
1 112050 400373 466123 666197 888560 332198
2 120997 887728 917384 701596 682327 189514
3 153035 332198 315644 745845 469035 800949
4 155607 544171 759047 992698 450960 799685
5 163607 908546 338957 694713 267589 406304
6 175816 469035 120997 459962 875044 447493
table(apply(df, 1, function(x) {length(unique(x))}))
6
100
table(apply(df, 2, function(x) {length(unique(x))}))
100
6
library(tidyverse)
df=data.frame(x=1:100)
df%>%
mutate(number = map(x, ~ glue::collapse(sample(x,5,replace=),",")))%>%
separate(number,into= glue::glue("review{1:5}"))
我有一个包含大约 100 个足球运动员号码的数据框 (df
)(如果有更多的球员注册,这个数字会增加)。每个 player_number
由 6 位数字组成(例如 178530)。
每个玩家都要评论5个其他玩家,所以最终所有玩家都会被另外5个评论。因此我想给每个 player_number
随机分配 5 个不同的玩家号码(来自 player_number
列)。为避免将评论分配给自己 and/or 玩家必须对同一玩家进行两次(或更多次)评论,每个 player_number
应该在每一列和每一行中只出现一次。 数据框应如下所示:
player_number review1 review2 review3 review4 review5
178530 207145 655600 443274 604060 804226
245678 947821 214525 332324 174589 868954
…
玩家178530需要审核玩家207145、655600等
对于 review1 列,我使用了:
set.seed(1)
df$review1 <- sample(df$player_number, nrow(df), replace=F)
这适用于 review1
,但将其应用于其他评论列会导致在多行中重复 player_number
。谁能帮助我,让每个 player_number
在每一列和每一行中只出现一次?提前致谢。
编辑:在之前的版本中我简化了 player_number 太多 (1:100)
您可以为此编写一个函数。这个想法是获取 100 个 ID 或玩家号码的向量;随机抽取 5 个 unique 起始值作为 5 个新向量的起始值并绑定它们以获得您的结果,其中在每一行和每一列中都没有找到超过一次的 ID。
例如,如果您有数字1到5(那个顺序),并且想将其中的3个数字分配给1到5的每个数字;在一行或一列中没有数字超过一次。
1 3 2 5
2 4 3 1
3 5 4 2
4 1 5 3
5 2 1 4
这是执行此操作的函数。
play <- function(v, i){
starts <- sample(2:length(v), i, replace=F)
v2 <- v
for(m in 1:i){
v2 <- cbind(v2, c(v[starts[m]:length(v)], v[0:(starts[m]-1)]) )
}
colnames(v2) <- c('id', paste0('R', 1:i))
return(v2)
}
试试吧。
play(1:5, 3)
这是一个类似的函数,它接受一个数据框,因为你在问题中要求它。
playDF <- function(df, i){
starts <- sample(1:nrow(df), i+1, replace=F)
sq2 <- NULL
for(m in 1:(i+1)){
sq2 <- cbind(sq2, c(df[starts[m]:nrow(df),], df[0:(starts[m]-1),]) )
}
sq2 <- as.data.frame(sq2)
colnames(sq2) <- c('player_number', paste0('review', 1:(i)))
return(sq2)
}
我已经为您的问题添加了示例数据。 运行 函数并将其应用于数据。
df <- data.frame(player_number=c(sample(111111:999999, 100, replace=F)))
playDF(df, 5)
可能不是最有效的,但这是一个仅使用基数 R 的解决方案。在这里,我一次只从 1:100 的向量中抽取 1 个数字,当前向量中没有已经存在的数字行和当前列。
对于第 100 行,这意味着数字是从长度为 1 的向量中采样的,这导致 sample
函数的行为不同。因此,为了防止这种意外行为,我好心地从 Sampling in R from vector of varying length 中授予了 sample.vec
自定义函数。
df <- data.frame(player_number = c(1:100))
df <- cbind(df, matrix(NA, 100, 5))
sample.vec <- function(x, ...) x[sample(length(x), ...)]
for(i in 1:100){
for(j in 2:6){
df[i,j] <- sample.vec(setdiff(c(1:100),c(df[i,], df[,j])), 1)
}
}
问题更改后的更新:如果您想使用那些 6 位数的自定义玩家号码,一个选项可以是将所有列转换为因子,使用 1:100 作为级别,使用实际玩家号码作为标签。所以在上面的代码之后,你可以做这样的事情:
set.seed(1); player_number = sort(sample(100000:999999, 100)) # in your data, just create this vector beforehand using the actual player numbers
df[] <- lapply(df, function(x) {factor(x, levels = c(1:100), labels = player_number)})
证明:
head(df)
player_number 1 2 3 4 5
1 112050 400373 466123 666197 888560 332198
2 120997 887728 917384 701596 682327 189514
3 153035 332198 315644 745845 469035 800949
4 155607 544171 759047 992698 450960 799685
5 163607 908546 338957 694713 267589 406304
6 175816 469035 120997 459962 875044 447493
table(apply(df, 1, function(x) {length(unique(x))}))
6
100
table(apply(df, 2, function(x) {length(unique(x))}))
100
6
library(tidyverse)
df=data.frame(x=1:100)
df%>%
mutate(number = map(x, ~ glue::collapse(sample(x,5,replace=),",")))%>%
separate(number,into= glue::glue("review{1:5}"))