Maison  >  Article  >  développement back-end  >  Comment faire fondre le dataframe pandas ?

Comment faire fondre le dataframe pandas ?

WBOY
WBOYavant
2024-02-09 23:30:14392parcourir

如何融化 pandas 数据框?

Contenu des questions

Sur la balise pandas, je vois souvent des utilisateurs poser des questions sur la fusion des dataframes chez les pandas. Je vais essayer de faire une question-réponse canonique (auto-réponse) sur ce sujet.

Je tiens à préciser :

  1. Qu’est-ce qui fond ?

  2. Comment utiliser le fondant ?

  3. Quand utiliser le fondant ?

J'ai vu quelques questions courantes sur la fonte, telles que :

  • Convertir les colonnes en lignes à l'aide de pandas : Celui-ci pourrait en fait être bon, mais plus d'explications seraient bien.

  • fonction pandas melt : Une bonne question avec une bonne réponse, mais un peu trop vague sans trop d'explications.

  • Melting pandas dataframe : Également une excellente réponse ! Mais c'est juste pour un cas précis, c'est simple, juste pd.melt(df)

  • pandas dataframe utilisant des colonnes comme lignes (fondues)  : Très soigné ! Mais le problème est qu'il ne répond qu'à la question spécifique posée par le PO, qui nécessite également l'utilisation de pivot_table.

Je vais donc essayer de faire une séance de questions-réponses canonique sur ce sujet.

Ensemble de données :

Je trouverai toutes les réponses dans cet ensemble de données de notes aléatoires pour des personnes aléatoires à des âges aléatoires (plus facile d'expliquer la réponse :d) :

import pandas as pd
df = pd.dataframe({'name': ['bob', 'john', 'foo', 'bar', 'alex', 'tom'],
                   'math': ['a+', 'b', 'a', 'f', 'd', 'c'],
                   'english': ['c', 'b', 'b', 'a+', 'f', 'a'],
                   'age': [13, 16, 16, 15, 15, 13]})
>>> df
   name math english  age
0   bob   a+       c   13
1  john    b       b   16
2   foo    a       b   16
3   bar    f      a+   15
4  alex    d       f   15
5   tom    c       a   13

Question :

Question 1 :

Comment fondre un dataframe pour que le dataframe d'origine devienne le suivant ?

    name  age  subject grade
0    bob   13  english     c
1   john   16  english     b
2    foo   16  english     b
3    bar   15  english    a+
4   alex   17  english     f
5    tom   12  english     a
6    bob   13     math    a+
7   john   16     math     b
8    foo   16     math     a
9    bar   15     math     f
10  alex   17     math     d
11   tom   12     math     c

Je veux le transposer de manière à ce qu'une colonne soit pour chaque matière et que les autres colonnes soient les noms répétés des élèves avec leur âge et leurs résultats.

Question 2 :

C'est similaire à la question 1, mais cette fois je veux que la question 1 affiche subject列只有math,我想过滤掉englishcolonne :

   name  age subject grades
0   bob   13    math     a+
1  john   16    math      b
2   foo   16    math      a
3   bar   15    math      f
4  alex   15    math      d
5   tom   13    math      c

Je veux que le résultat ressemble à celui ci-dessus.

Question 3 :

Si je devais regrouper les fondus et les trier en fonction des scores des élèves, comment ferais-je pour obtenir le résultat souhaité comme celui-ci :

  value             name                subjects
0     a         foo, tom           math, english
1    a+         bob, bar           math, english
2     b  john, john, foo  math, english, english
3     c         tom, bob           math, english
4     d             alex                    math
5     f        bar, alex           math, english

Je dois le trier avec les noms séparés par des virgules et les subjects séparés par des virgules respectivement dans le même ordre.

Question 4 :

Comment puis-je dégeler une trame de données fondue ? Disons que j'ai fait fondre ce dataframe :

df = df.melt(id_vars=['name', 'age'], var_name='subject', value_name='grades')

Devenez :

    name  age  subject grades
0    bob   13     math     a+
1   john   16     math      b
2    foo   16     math      a
3    bar   15     math      f
4   alex   15     math      d
5    tom   13     math      c
6    bob   13  english      c
7   john   16  english      b
8    foo   16  english      b
9    bar   15  english     a+
10  alex   15  english      f
11   tom   13  english      a

Alors, comment puis-je le reconvertir dans le bloc de données d'origine, comme indiqué ci-dessous ?

   name math english  age
0   bob   a+       c   13
1  john    b       b   16
2   foo    a       b   16
3   bar    f      a+   15
4  alex    d       f   15
5   tom    c       a   13

Question 5 :

Que ferais-je si je voulais regrouper les élèves par nom et séparer les matières et les notes par des virgules ?

   name        subject grades
0  alex  math, english   d, f
1   bar  math, english  f, a+
2   bob  math, english  a+, c
3   foo  math, english   a, b
4  john  math, english   b, b
5   tom  math, english   c, a

Je veux un dataframe comme ci-dessus.

Question 6 :

Si je devais fondre complètement mon dataframe avec toutes les colonnes comme valeurs, que ferais-je ?

     Column Value
0      Name   Bob
1      Name  John
2      Name   Foo
3      Name   Bar
4      Name  Alex
5      Name   Tom
6      Math    A+
7      Math     B
8      Math     A
9      Math     F
10     Math     D
11     Math     C
12  English     C
13  English     B
14  English     B
15  English    A+
16  English     F
17  English     A
18      Age    13
19      Age    16
20      Age    16
21      Age    15
22      Age    15
23      Age    13

Je veux un dataframe comme ci-dessus. Toutes les colonnes en tant que valeurs.


Bonne réponse


Remarque pour la version pandas < 0.20.0  : j'utiliserai df.melt(...) 作为我的示例,但您需要使用 pd.melt(df, .. .) à la place.

Référence du document :

La plupart des solutions ici fonctionneront avec melt,所以要知道方法melt, donc pour savoir comment veuillez consulter les

instructions de documentation

.

Logique de fusion :

    Melting fusionne plusieurs colonnes, convertit la trame de données de large en longue et résout le problème 1 (voir ci-dessous).
  1. Nous obtenons d’abord la trame de données d’origine.
  2. mathenglishEnsuite, melt fusionne d'abord les colonnes

    et duplique la trame de données (plus longue).
  3. subject 列,它分别是 gradesEnfin, il ajoute

    thèmes pour les valeurs des colonnes :

meltC'est la logique simple de la fonction

.

Solution :

Question 1 :

Le problème 1 peut être résolu en utilisant pd.dataframe.melt

en utilisant le code suivant :

print(df.melt(id_vars=['name', 'age'], var_name='subject', value_name='grades'))
id_vars 参数传递给 ['name', 'age'],然后自动将 value_vars 设置为其他列(['math', 'english']Ce code convertit

), qui est la transposition, dans ce format.

Vous pouvez également utiliser stack解决问题 1 >

comme ci-dessous :

print(
    df.set_index(["name", "age"])
    .stack()
    .reset_index(name="grade")
    .rename(columns={"level_2": "subject"})
    .sort_values("subject")
    .reset_index(drop=true)
)
nameage 列设置为索引,并堆叠其余列 mathenglish,并重置索引并指定 grade 作为列名称,然后将其他列重命名为 level_2phpcnendcphp cn 到 <code>subject 然后按subjectCe code définit les colonnes name et age comme index et empile les colonnes restantes

et réinitialise l'index et spécifie grade comme nom de colonne, Renommez ensuite les autres colonnes en level_2phpcnendcphp cn en <code>subject puis appuyez sur la colonne subject et enfin réinitialisez à nouveau l'index.

Les deux solutions en sortie : 🎜
    name  age  subject grade
0    bob   13  english     c
1   john   16  english     b
2    foo   16  english     b
3    bar   15  english    a+
4   alex   17  english     f
5    tom   12  english     a
6    bob   13     math    a+
7   john   16     math     b
8    foo   16     math     a
9    bar   15     math     f
10  alex   17     math     d
11   tom   12     math     c

问题 2:

这和我的第一个问题类似,但是这个我只在 math 列中进行过滤,这时候 value_vars 参数就可以派上用场了,如下所示:

print(
    df.melt(
        id_vars=["name", "age"],
        value_vars="math",
        var_name="subject",
        value_name="grades",
    )
)

或者我们也可以使用 stack 与列规格:

print(
    df.set_index(["name", "age"])[["math"]]
    .stack()
    .reset_index(name="grade")
    .rename(columns={"level_2": "subject"})
    .sort_values("subject")
    .reset_index(drop=true)
)

这两种解决方案都给出:

   name  age subject grade
0   bob   13    math    a+
1  john   16    math     b
2   foo   16    math     a
3   bar   15    math     f
4  alex   15    math     d
5   tom   13    math     c

问题 3:

问题3可以通过melt解决和 groupby,使用 agg 函数和 ' , '.join,如下所示:

print(
    df.melt(id_vars=["name", "age"])
    .groupby("value", as_index=false)
    .agg(", ".join)
)

它会融合数据框,然后按等级进行分组,聚合它们并用逗号将它们连接起来。

stack也可以用来解决这个问题,与 stackgroupby 如下所示:

print(
    df.set_index(["name", "age"])
    .stack()
    .reset_index()
    .rename(columns={"level_2": "subjects", 0: "grade"})
    .groupby("grade", as_index=false)
    .agg(", ".join)
)

这个 stack 函数只是转置数据帧以相当于 melt 的方式,然后重置索引,重命名列、组和聚合。

两种解决方案输出:

  grade             name                subjects
0     a         foo, tom           math, english
1    a+         bob, bar           math, english
2     b  john, john, foo  math, english, english
3     c         bob, tom           english, math
4     d             alex                    math
5     f        bar, alex           math, english

问题 4:

这可以通过 pivot_table 来解决。我们必须指定参数 valuesindexcolumns 以及 aggfunc

我们可以用下面的代码来解决这个问题:

print(
    df.pivot_table("grades", ["name", "age"], "subject", aggfunc="first")
    .reset_index()
    .rename_axis(columns=none)
)

输出:

   name  age english math
0  alex   15       f    d
1   bar   15      a+    f
2   bob   13       c   a+
3   foo   16       b    a
4  john   16       b    b
5   tom   13       a    c

融化的数据帧被转换回与原始数据帧完全相同的格式。

我们首先旋转融化的数据框,然后重置索引并删除列轴名称。

问题 5:

问题5可以通过melt解决和 groupby 如下所示:

print(
    df.melt(id_vars=["name", "age"], var_name="subject", value_name="grades")
    .groupby("name", as_index=false)
    .agg(", ".join)
)

融化并按 name 分组。

或者您可以stack: p>

print(
    df.set_index(["name", "age"])
    .stack()
    .reset_index()
    .groupby("name", as_index=false)
    .agg(", ".join)
    .rename({"level_2": "subjects", 0: "grades"}, axis=1)
)

两个代码输出:

   name       subjects grades
0  alex  math, english   d, f
1   bar  math, english  f, a+
2   bob  math, english  a+, c
3   foo  math, english   a, b
4  john  math, english   b, b
5   tom  math, english   c, a

问题 6:

问题6可以通过melt解决并且不需要指定列,只需指定预期的列名称:

print(df.melt(var_name='column', value_name='value'))

这会融化整个数据框。

或者您可以stack: p>

print(
    df.stack()
    .reset_index(level=1)
    .sort_values("level_1")
    .reset_index(drop=true)
    .set_axis(["column", "value"], axis=1)
)

两个代码输出:

     Column Value
0       Age    16
1       Age    15
2       Age    15
3       Age    16
4       Age    13
5       Age    13
6   English    A+
7   English     B
8   English     B
9   English     A
10  English     F
11  English     C
12     Math     C
13     Math    A+
14     Math     D
15     Math     B
16     Math     F
17     Math     A
18     Name  Alex
19     Name   Bar
20     Name   Tom
21     Name   Foo
22     Name  John
23     Name   Bob

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer