Mes données ressemblent à ceci:
rank 1 2 3 4 5 6 rank_match 1: 3 -0.6264538 0.3295078 0.5757814 -0.62124058 -0.01619026 0.91897737 0.3295078 2: 4 0.1836433 -0.8204684 -0.3053884 -2.21469989 0.94383621 0.78213630 -0.3053884 3: 2 -0.8356286 0.4874291 1.5117812 1.12493092 0.82122120 0.07456498 1.1249309 4: 1 1.5952808 0.7383247 0.3898432 -0.04493361 0.59390132 -1.98935170 1.5952808
Je voudrais ajouter une nouvelle colonne rank_match qui trouve la nième (prise à partir du rang colonne) la plus grande valeur de la ligne des colonnes nommées 1 à 6 . Par exemple, la première ligne chercherait la troisième plus grande valeur de la ligne des colonnes nommées 1 à 6 , soit 0,3295078.
Quelque chose comme ça (mais bien sûr, cela ne fonctionne pas):
dt[,rank_match := (sort(`1`:`6`, decreasing = TRUE)[rank])] dt[,rank_match := (sort(.SD, decreasing = TRUE)[rank]), .SDcols=`1`:`6`]
La sortie devrait ressembler à ceci:
set.seed(1) dt <- data.table(rank=c(3,4,2,1),`1`=rnorm(4),`2`=rnorm(4),`3`=rnorm(4),`4`=rnorm(4),`5`=rnorm(4),`6`=rnorm(4)) rank 1 2 3 4 5 6 1: 3 -0.6264538 0.3295078 0.5757814 -0.62124058 -0.01619026 0.91897737 2: 4 0.1836433 -0.8204684 -0.3053884 -2.21469989 0.94383621 0.78213630 3: 2 -0.8356286 0.4874291 1.5117812 1.12493092 0.82122120 0.07456498 4: 1 1.5952808 0.7383247 0.3898432 -0.04493361 0.59390132 -1.98935170
Merci tellement.
5 Réponses :
Une option est de grouper par séquence de lignes, spécifiez les colonnes d'intérêt à partir de la colonne 2, unlist , le sous-ensemble de Data.table, sort dans l'ordre décroissant , sous-définissez la valeur en fonction de la colonne 'rank' et attribuez-la à 'rank_match'
library(purrr)
dt[, rank_match := pmap_dbl(.SD, ~ c(...) %>%
{sort(-.[-1])[.[1]]})]
Une autre option serait de fondre puis d'obtenir le correspondant valeur de la colonne 'value'
dt[, rank_match := melt(.SD, 'rank')[, value[order(-value)[rank]], rank]$V1]
Ou une approche compacte suggérée par @IceCreamToucan
out <- melt(dt, id.var = c('rn', 'rank'))[order(-value),
value[rank[1]] , .(rn)][order(rn)]$V1
dt[, rank_match := out][, rn := NULL][]
Ou utilisez pmap (de purrr ) pour parcourir les lignes
dt[, rank_match := sort(unlist(.SD), decreasing = TRUE)[rank],
1:nrow(dt), .SDcols = 2:ncol(dt) ]
dt
# rank 1 2 3 4 5 6 rank_match
#1: 3 -0.6264538 0.3295078 0.5757814 -0.62124058 -0.01619026 0.91897737 0.3295078
#2: 4 0.1836433 -0.8204684 -0.3053884 -2.21469989 0.94383621 0.78213630 -0.3053884
#3: 2 -0.8356286 0.4874291 1.5117812 1.12493092 0.82122120 0.07456498 1.1249309
#4: 1 1.5952808 0.7383247 0.3898432 -0.04493361 0.59390132 -1.98935170 1.5952808
appliquer la fonction indiquée sur chaque ligne de .SD:
rank 1 2 3 4 5 6 rank_match 1: 3 -0.6264538 0.3295078 0.5757814 -0.62124058 -0.01619026 0.91897737 0.3295078 2: 4 0.1836433 -0.8204684 -0.3053884 -2.21469989 0.94383621 0.78213630 -0.3053884 3: 2 -0.8356286 0.4874291 1.5117812 1.12493092 0.82122120 0.07456498 1.1249309 4: 1 1.5952808 0.7383247 0.3898432 -0.04493361 0.59390132 -1.98935170 1.5952808
giving:
dt[, rank_match := apply(.SD, 1, function(x) -sort(-x[-1])[x[1]])]
Une autre excellente solution qui fonctionne bien @G. Grothendieck Merci.
dt[, rank_match := apply(.SD, 1, function(x) x[order(-x)][rank]), by = rank, .SDcols = `1`:`6`] dt rank 1 2 3 4 5 6 rank_match 1: 3 -0.6264538 0.3295078 0.5757814 -0.62124058 -0.01619026 0.91897737 0.3295078 2: 4 0.1836433 -0.8204684 -0.3053884 -2.21469989 0.94383621 0.78213630 -0.3053884 3: 2 -0.8356286 0.4874291 1.5117812 1.12493092 0.82122120 0.07456498 1.1249309 4: 1 1.5952808 0.7383247 0.3898432 -0.04493361 0.59390132 -1.98935170 1.5952808
Merci @snoram cette réponse me semble la plus lisible, bien que toutes les autres fonctionnent également.
DescTools :: Large renvoie les n èmes plus grands éléments d'un vecteur sans trier le tout. Je ne sais pas comment cela se compare à dt [order (-value) [rank], ...] .
library(DescTools) library(data.table) dt[, rank_match := melt(dt, 'rank')[, Large(value, rank)[1], rank]$V1] # rank 1 2 3 4 5 6 rank_match # 1: 3 -0.6264538 0.3295078 0.5757814 -0.62124058 -0.01619026 0.91897737 0.3295078 # 2: 4 0.1836433 -0.8204684 -0.3053884 -2.21469989 0.94383621 0.78213630 -0.3053884 # 3: 2 -0.8356286 0.4874291 1.5117812 1.12493092 0.82122120 0.07456498 1.1249309 # 4: 1 1.5952808 0.7383247 0.3898432 -0.04493361 0.59390132 -1.98935170 1.5952808
Remarque: Si certaines lignes ont le même rang, vous devez utiliser la logique rn / numéro de ligne comme dans la réponse d'Akrun.