我认为这在R中是一个相当具有挑战性的数据操作问题,并且很难构建一个能够实现这一目标的函数。背景是组织篮球运动员,他们在不同的位置上一起进入阵容,取决于每个球员的位置。为清楚起见,这里是我正在使用的数据帧的一个示例,有两种不同的形式:
dput(my_df)
structure(list(Name = c("C.J. McCollum", "DeMar DeRozan", "Jimmy Butler",
"Jonas Valanciunas", "Kevin Durant", "Markieff Morris", "Pascal Siakam",
"Pau Gasol"), Pos1 = c("PG", "SG", "SG", "C", "SF", "SF", "PF",
"C"), Pos2 = c("SG", "", "SF", "", "PF", "PF", "", "")), .Names = c("Name",
"Pos1", "Pos2"), class = "data.frame", row.names = c(18L, 33L,
62L, 68L, 78L, 92L, 106L, 111L))
my_df
Name Pos1 Pos2
18 C.J. McCollum PG SG
33 DeMar DeRozan SG
62 Jimmy Butler SG SF
68 Jonas Valanciunas C
78 Kevin Durant SF PF
92 Markieff Morris SF PF
106 Pascal Siakam PF
111 Pau Gasol C
dput(my_df2)
structure(list(Name = c("C.J. McCollum", "DeMar DeRozan", "Jimmy Butler",
"Jonas Valanciunas", "Kevin Durant", "Markieff Morris", "Pascal Siakam",
"Pau Gasol"), Pos1 = c("PG", "SG", "SG", "C", "SF", "SF", "PF",
"C"), Pos2 = c("SG", "", "SF", "", "PF", "PF", "", ""), PG = c(1,
0, 0, 0, 0, 0, 0, 0), SG = c(1, 1, 1, 0, 0, 0, 0, 0), SF = c(0,
0, 1, 0, 1, 1, 0, 0), PF = c(0, 0, 0, 0, 1, 1, 1, 0), C = c(0,
0, 0, 1, 0, 0, 0, 1), BackupG = c(1, 1, 1, 0, 0, 0, 0, 0), BackupF = c(0,
0, 1, 0, 1, 1, 1, 0), Man8 = c(1, 1, 1, 1, 1, 1, 1, 1)), .Names = c("Name",
"Pos1", "Pos2", "PG", "SG", "SF", "PF", "C", "BackupG", "BackupF",
"Man8"), row.names = c(18L, 33L, 62L, 68L, 78L, 92L, 106L, 111L
), class = "data.frame")
my_df2
Name Pos1 Pos2 PG SG SF PF C BackupG BackupF Man8
18 C.J. McCollum PG SG 1 1 0 0 0 1 0 1
33 DeMar DeRozan SG 0 1 0 0 0 1 0 1
62 Jimmy Butler SG SF 0 1 1 0 0 1 1 1
68 Jonas Valanciunas C 0 0 0 0 1 0 0 1
78 Kevin Durant SF PF 0 0 1 1 0 0 1 1
92 Markieff Morris SF PF 0 0 1 1 0 0 1 1
106 Pascal Siakam PF 0 0 0 1 0 0 1 1
111 Pau Gasol C 0 0 0 0 1 0 0 1
在篮球阵容中,我们想要为篮球中的5个位置(PG,SG,PF,SF,C)设置1个球员,我们还需要1个后卫(PG或SG是后卫),1备用前锋(PF或FS是前锋),以及可以打任何位置的第8位玩家。有了这8名队员,我们可以用这种方式构建阵容:
Name
PG C.J. McCollum
SG DeMar DeRozan
PF Kevin Durant
SF Markieff Morris
C Pau Gasol
Backup G Jimmy Butler
Backup F Pascal Siakam
8th Man Jonas Valanciunas
当然,这有一定的灵活性(凯文杜兰特和马基夫莫里斯本可以转换,事实上有几个球员可以在第二个数据帧中切换位置)。我希望能够以相当快的速度将my_df组织成第二种数据帧格式,从my_df获取Pos1和Pos2列,能够检查第二个数据帧的rownames,然后填写播放器名称。
然而,这有一个难题。值得注意的是,并非所有玩家都有第二个位置,但那些拥有第二个位置的玩家可以在两个位置中列出。 (例如,Jimmy Butler可以设置为SG,SF,备用G,备用F或第8人,而Pau Gasol只能设置为C或第8人)。此外,虽然C.J. McCollum被列为PG和SG,但他是my_df中唯一被列为PG的玩家,因此必须进入第二个数据帧的PG行。
任何想法都赞赏这个!如果需要,我可以提供更多背景信息。
(编辑:可能编辑my_df,添加Pos3,Pos4,Pos5列以了解玩家是否可以作为备份G,备份F或第8人,也可以提供帮助,这是我目前正在使用的内容)。< / p>
编辑 - 请参阅Simplify this grid such that each row and column has 1 value了解我的问题的修订版本,这是一个更简单的问题需要解决,但会为我提供这个问题的解决方案!
答案 0 :(得分:0)
如果有结果,这种方法可以保证返回结果,实际上它将返回所有可行的组合。
st<-as.matrix(my_df2[4:dim(my_df2)[2]]) # Make a numeric matrix
## allCombinationsAux may not be necessary if you are using a combinatorics library
allCombinationsAux<-function(z,nreg,x){
if(sum(nreg)>1){
innerLoop<-do.call(rbind,lapply(x[nreg&(z!=x)], test1,nreg&(z!=x),x))
ret<-cbind(z,innerLoop )
}
else{
ret<-x[nreg]
}
ret
}
## Find all the possible row combinations for the matrix
combs<-do.call(rbind,lapply(x,function(y) allCombinationsAux(y,y!=x,x)))
## Identify which combinations are valid
inds<-which(apply(combs,1,function(x) sum(diag(st[x,]))==8))
## Select valid matricies
validChoices<-lapply(inds,function(x) st[combs[x,],])
my_df2
要使输出看起来像您的示例,您可以运行
validChoices<-lapply(inds,function(x) {
matr<-st[combs[x,],]
retVal<-data.frame(Name=my_df2[combs[x,],"Name"])
rownames(retVal)<-colnames(matr)
retVal
})