繁体   English   中英

R:5列中一列的随机值

[英]R: Random values from one column in 5 columns

我有一个包含大约100个足球运动员号码的数据帧( df )(如果更多的球员注册,则数量增加)。 每个player_number由6位数组成(例如178530)。

每个玩家都应该回顾5个其他玩家,所以最终所有玩家都会被其他玩家评价。 因此,我想将5个不同的玩家编号(从player_number列)随机分配给每个player_number 为了防止将评论分配给他们自己和/或必须两次(或更多)查看同一玩家的玩家, 每个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个新向量抽取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函数表现不同。 因此,为了防止这种意外行为,我赐予了来自不同长度矢量的R采样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位数的自定义播放器编号,可以选择将alll列转换为因子,使用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}"))

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM