J'ai besoin de faire quelque chose de très spécifique et j'essaie de le faire de la bonne manière, surtout que je veux que ce soit optimisé.
J'ai donc un DataFrame qui ressemble à ceci :
v = ["x","y","z"][rand(1:3, 10)]
df = DataFrame(Any[collect(1:10), v, rand(10)], [:USER_ID, :GENRE_MAIN, :TOTAL_LISTENED])
Row USER_ID GENRE_MAIN TOTAL_LISTENED
Int64 String Float64
1 1 x 0.237186
12 1 y 0.237186
13 1 x 0.254486
2 2 z 0.920804
3 3 y 0.140626
4 4 x 0.653306
5 5 x 0.83126
6 6 x 0.928973
7 7 y 0.519728
8 8 x 0.409969
9 9 z 0.798064
10 10 x 0.701332
Je veux l'agréger par utilisateur (j'ai beaucoup de lignes par user_id) et faire de nombreux calculs.
J'ai besoin de calculer le top 1 ,2 ,3 ,4 ,5 genre, nom d'album, nom d'artiste par user_id et ses valeurs respectives (le total_listened qui correspond) et cela doit être comme ceci :
USER_ID ALBUM1_NAME ALBUM2_NAME | ALBUM1_NAME_VALUE | ALBUM2_NAME_VALUES | ...... GENRE1 GENRE2
Une ligne par user_id .
J'ai obtenu cette solution qui correspond à 90% de ce que je voulais mais je ne peux pas la modifier pour inclure les valeurs de total_listened :
using DataFrames, Pipe, Random, Pkg
Pkg.activate(".")
Pkg.add("DataFrames")
Pkg.add("Pipe")
Random.seed!(1234)
df = DataFrame(USER_ID=rand(1:10, 80),
GENRE_MAIN=rand(string.("genre_", 1:6), 80),
ALBUM_NAME=rand(string.("album_", 1:6), 80),
ALBUM_ARTIST_NAME=rand(string.("artist_", 1:6), 80))
function top5(sdf, col, prefix)
return @pipe groupby(sdf, col) |>
combine(_, nrow) |>
sort!(_, :nrow, rev=true) |>
first(_, 5) |>
vcat(_[!, 1], fill(missing, 5 - nrow(_))) |>
DataFrame([string(prefix, i) for i in 1:5] .=> _)
end
@pipe groupby(df, :USER_ID) |>
combine(_,
x -> top5(x, :GENRE_MAIN, "genre"),
x -> top5(x, :ALBUM_NAME, "album"),
x -> top5(x, :ALBUM_ARTIST_NAME, "artist"))
Un exemple :
Pour l'utilisateur 1 du DataFrame qui vient d'être créé, je veux que le résultat soit :
Row USER_ID GENRE1 GENRE2 GENRE1_VALUE GENRE2_VALUE ......
Int64 String String Float64 Float64
1 1 x y 0.491672 0.237186. ......
Je n'ai pris que le GENRE, mais je veux aussi le faire pour ALBUM_NAME, ALBUM_ARTIST_NAME.
Je veux aussi qu'après avoir fait un top rank % , classer les utilisateurs par total_listened et calculer leur percentile. pour les classer par top5%, top10%, top20% du total Je peux calculer le quantile étiqueté que je veux avec
x = .05
quantile(df.TOTAL_LISTENED, x)
et ensuite mettre tous les total_listened des utilisateurs qui sont supérieurs à ce quantile mais je ne sais pas comment le calculer correctement dans le combine...
Merci de votre attention.