我有一个这样的数据框:
a b c d e
1 47Z TS2 TS2 3SU 3SU
2 TS2 47Z 3SU K5S 47Z
3 3SU A2D A2D 47Z A2D
4 FZT 3SU FZT FZT RF9
5 A2D K5S TS2
每列代表一个功能的排名(此处为a-d)。排名中使用的代码不得出现在每一列中(但它们可以)并且排名的长度不同。在原始文件中,大约有60个排名/列,每个列有10-20个代码。
所以我现在想要选择排名中的前x个代码(在这个例子中x = 2),之前没有选择过两次以上。对于上面的例子,这将是结果:
a b c d e
1 47Z TS2 3SU 3SU A2D
2 TS2 47Z A2D K5S RF9
外观的顺序并不重要。
我必须承认,如果不使用多个for循环,我不知道如何实现它。 谢谢你的帮助!
答案 0 :(得分:1)
这是使用for循环的可能解决方案:
getTopRanking <- function(df,topN=2,maxRep=2){
uniqueVals <- unique(na.omit(unlist(df)))
repetitions <- data.frame(count=rep.int(0,length(uniqueVals)),row.names=uniqueVals)
res <- vector(mode='list',length=ncol(df))
for(i in 1:ncol(df)){
colvals <- df[,i]
topNVals <- head(colvals[colvals %in%
row.names(repetitions)[repetitions$count < maxRep]],topN)
# pad with NAs (in case we can't find topN elements)
topNVals <- c(topNVals, rep.int(NA,max(topN-length(topNVals),0)))
res[[i]] <- topNVals
repetitions[na.omit(topNVals),1] <- repetitions[na.omit(topNVals),1] + 1
}
result <- do.call(cbind.data.frame,res)
colnames(result) <- colnames(df)
return(result)
}
用法示例:
# your example data.frame
df <-
data.frame(
a = c("47Z", "TS2", "3SU", "FZT", "A2D"),
b = c("TS2", "47Z", "A2D", "3SU", "K5S"),
c = c("TS2", "3SU", "A2D", "FZT", NA),
d = c("3SU", "K5S", "47Z", "FZT", "TS2"),
e = c("3SU", "47Z", "A2D", "RF9", NA),
stringsAsFactors=F)
res <- getTopRanking(df,topN=2,maxRep=2)
> res
a b c d e
1 47Z TS2 3SU 3SU A2D
2 TS2 47Z A2D K5S RF9