3
votes

Comment puis-je catégoriser toutes les colonnes d'une donnée à la fois? (Faire en sorte que toutes les valeurs deviennent élevées, moyennes, faibles)

J'essaie de convertir toutes les valeurs de mon ensemble de données en valeurs catégorielles, je veux que toutes les valeurs numériques soient catégorisées en faible, moyenne ou élevée dépend de leurs valeurs de quantile.

Donc, si la valeur est inférieure à 25% la série, elle sera convertie en "Low"

J'ai essayé d'utiliser assign puis appliqué une fonction que je fournis:

    Year  Month  Central Equatoria  Eastern Equatoria  Gogrial  Jonglei
0   2014     10                High             Medium      Low      Medium  
1   2014     11                Low              Medium      Low     high

Cependant, le le code ne fonctionne pas bien. Je l'ai également essayé via iterrows mais je me demande s'il existe un moyen plus rapide de le faire?

Voici les données que je voulais convertir, tous les nombres hors année et mois doivent être classés en bas, moyen Élevé, en fonction de leur valeur quantile.

    Year  Month  Central Equatoria  Eastern Equatoria  Gogrial  Jonglei
0   2014     10                6.0                1.0      0.0      3.0   
1   2014     11                4.0                3.0      0.0     12.0   
2   2014     12                3.0                5.0      0.0     11.0   
3   2015      1                7.0                2.0      0.0      4.0   
4   2015      2                5.0                5.0      0.0     10.0   
5   2015      3                7.0                5.0      0.0      8.0   
6   2015      4                4.0                1.0      0.0      6.0   
7   2015      5                5.0                0.0      0.0      7.0   
8   2015      6                4.0                1.0      0.0      6.0   
9   2015      7               15.0                2.0      0.0      9.0   
10  2015      8               10.0                7.0      0.0      9.0   
11  2015      9               12.0                0.0      0.0      8.0   
12  2015     10               12.0                0.0      0.0      5.0   
13  2015     11                8.0                5.0      0.0     10.0   
14  2015     12                5.0                7.0      0.0      3.0 

Résultat attendu: (Exemple)

def turn_into_categorical(row):
    quantile_level = [.25, .5, .75]
    for r in row:
        cut = refugees_T_F_V_P_full_data.r.quantile(quantile_level)
        if r >= cut[.75]:
            return "High"
        elif r >= cut[.25] and r < cut[0.75]:
            return "Average"
        else:
            return "Low"

refugees_T_F_V_P_full_data.apply(turn_into_categorical, axis = 1)


1 commentaires

En guise de commentaire, c'est une question bien écrite avec un problème intéressant - merci!


4 Réponses :


1
votes

Une idée utilisant pd.DataFrame.quantile avec pd.Series.cut:

print(df)

    Year  Month CentralEquatoria EasternEquatoria Gogrial Jonglei
0   2014     10           Medium              Low     Low     Low
1   2014     11              Low           Medium     Low    High
2   2014     12              Low           Medium     Low    High
3   2015      1           Medium           Medium     Low     Low
4   2015      2           Medium           Medium     Low    High
5   2015      3           Medium           Medium     Low  Medium
6   2015      4              Low              Low     Low  Medium
7   2015      5           Medium              Low     Low  Medium
8   2015      6              Low              Low     Low  Medium
9   2015      7             High           Medium     Low  Medium
10  2015      8             High             High     Low  Medium
11  2015      9             High              Low     Low  Medium
12  2015     10             High              Low     Low     Low
13  2015     11           Medium           Medium     Low    High
14  2015     12           Medium             High     Low     Low

Résultat:

XXX


4 commentaires

Si l'OP est prêt à prendre des étiquettes int et non des chaînes, nous pourrions vectoriser cela, je pense. J'essaye juste de finaliser une idée


@roganjosh, pd.cut Je crois qu'il est entièrement vectorisé, les séries "string" à la fin sont en fait des catégoriques efficaces, c'est-à-dire soutenues par des tableaux d'entiers.


Ah merde, j'ai vu la boucle for et je l'ai mal lu! J'allais pour np.digitize . Vous avez raison AFAIK.


J'ai essayé le code mais il renvoie la même erreur qui m'a eue lorsque j'ai essayé le code de @ yatu ValueError: Les bords du bac doivent être uniques: array ([0., 0., 5., 26.]). Vous pouvez supprimer les arêtes en double en définissant le kwarg "duplicates"



2
votes

On dirait que vous voulez pd.qcut , qui fait précisément cela. À partir de la documentation:

Fonction de discrétisation basée sur les quantiles

Vous pourriez donc appliquez pd.qcut le long des colonnes du dataframe à partir de Central Equatoria , en spécifiant les quantiles que vous souhaitez utiliser la série avec q = [0, 0.25, 0.75, 1.0]

       Central Equatoria Eastern Equatoria Gogrial Jonglei
0            medium              low     low     low
1               low           medium     low    high
2               low           medium     low    high
3            medium           medium     low     low
4            medium           medium     low    high
5            medium           medium     low  medium
6               low              low     low  medium
7            medium              low     low  medium
8               low              low     low  medium
9              high           medium     low  medium
10             high             high     low  medium
11             high              low     low  medium
12             high              low     low     low
13           medium           medium     low    high
14           medium             high     low     low

Sortie

df.loc[:,'Central Equatoria':].apply(lambda x: pd.qcut(x, q=[0, 0.25, 0.75, 1.0], 
                                    labels =['low','medium','high']) 
                                    if not x.nunique() == 1 else 'low'))


8 commentaires

Meilleure solution que la mienne :) .. en gros, cela combine les méthodes Pandas quantile et cut .


Oui, il se range directement en utilisant les informations quantiles. Merci :)


J'ai essayé d'implémenter le vôtre et le code de @jpp, mais il semble que la fonction pd.qcut renvoie toujours l'erreur ValueError: ("Les bords du bac doivent être uniques: array ([0., 0., 2., 7.]). \ NVous pouvez supprimer les arêtes en double en définissant le 'doublons' kwarg ", 'survenu à l'index Northern Bahr el Ghazal')


J'ai essayé de rechercher une solution pour cela à partir d'ici lien et j'ai ajouté un argument duplicates = 'drop' , mais il renvoie toujours ValueError: ('Les étiquettes de casier doivent être un de moins que le nombre d'arêtes', 's'est produite à l'index du Bahr el Ghazal du Nord')


le code complet est ici réfugiés_T_F_V_P_full_data.iloc [:, 2:]. apply (lambda x: pd.qcut (x, duplicates = 'drop', q = [0, 0.25, 0.75, 1.0], labels = [' faible ',' moyen ',' élevé ']) sinon x.nunique () == 1 sinon' faible ')


L'ensemble de données pour cette question peut être trouvé ici sur GitHub: lien < / a>


Je ne peux malheureusement pas vérifier maintenant, jettera un coup d'œil plus tard


Les bords du bac doivent être uniques: array ([0., 0., 2., 7.]) est clair. Vous avez 0 deux fois. Comment pouvez-vous bin des valeurs entre 0 et 0? Il existe un hack rapide pour résoudre ce problème, mais vous comprendrez mieux comment vous avez des valeurs en double dans vos bacs.



0
votes

Utilisation de pd.cut () et df.apply():

df.iloc[:,2:]=df.iloc[:,2:].apply(lambda x:pd.cut(x, 3, labels=['Low','Med','High']), axis=1)

    Year    Month   Central_Equatoria   Eastern_Equatoria   Gogrial Jonglei
0   2014    10      High    Low         Low                 Med
1   2014    11      Low     Low         Low                 High
2   2014    12      Low     Med         Low                 High
3   2015    1       High    Low         Low                 Med
4   2015    2       Med     Med         Low                 High
5   2015    3       High    Med         Low                 High


0 commentaires

0
votes

Finit par utiliser la mode la plus ancienne:

new_df = pd.DataFrame()
name_list = list(df)

for name in name_list:
    if name != 'Year' and name != 'Month':
        new_row = []
        quantiles = df[name].quantile([.25, .5, .75])
        row_list = df[name].tolist()
        for i, value in enumerate(row_list):
            if value < quantiles[.25]:
                new_row.append("Low")
            elif value < quantiles[.75] and value >= quantiles[.25]:
                new_row.append("Average")
            else:
                new_row.append("High")
        series = pd.Series(new_row)
        new_df[name] = series.values

new_df.head()


0 commentaires