如何融化 pandas 数据框?

2024-02-09

On the pandas /questions/tagged/pandas标签,我经常看到用户询问有关在 pandas 中融化数据框的问题。我将尝试针对这个主题进行规范的问答(自我回答)。

我要澄清一下:

  1. 什么是熔化?

  2. 如何使用熔体?

  3. 什么时候使用熔体?

我看到一些关于熔化的更热门的问题,例如:

  • 使用 Pandas 将列转换为行 https://stackoverflow.com/questions/28654047/pandas-convert-some-columns-into-rows: 这个其实还可以,但是多解释一下就更好了。

  • 熊猫融化功能 https://stackoverflow.com/questions/34830597/pandas-melt-function: 这个问题很好,答案也很好,但是有点太模糊了,没有太多解释。

  • 融化 pandas 数据框 https://stackoverflow.com/questions/46020139/melting-a-pandas-dataframe: 也是一个很好的答案!但这仅适用于特定情况,这很简单,仅pd.melt(df)

  • Pandas 数据框使用列作为行(融化) https://stackoverflow.com/questions/54041992/pandas-dataframe-use-columns-as-rows-melt: 井井有条!但问题是,这只是针对OP提出的具体问题,这也需要使用pivot_table以及。

所以我将尝试针对这个主题进行规范的问答。



Dataset:

我将在这个随机年龄的随机人的随机成绩数据集上获得所有答案(更容易解释答案: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
>>>

问题:

我将遇到一些问题,这些问题将在下面的自我回答中得到解决。

问题一:

如何融化数据框以使原始数据框变为以下内容?

    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:

这和问题1类似,但是这次我想做问题1的输出Subject列只有Math,我想过滤掉English column:

   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

我希望输出像上面那样。

问题3:

如果我要对熔化进行分组并按学生的分数对学生进行排序,我将如何做到这一点,以获得如下所示的所需输出:

  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

我需要订购它,名称用逗号分隔,还有Subjects分别以相同的顺序用逗号分隔。

问题4:

我会怎样unmelt融化的数据框?假设我已经融化了这个数据框:

print(df.melt(id_vars=['Name', 'Age'], var_name='Subject', value_name='Grades'))

成为:

    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

那么我如何将其转换回原始数据框,如下所示?

   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

我该怎么做呢?

问题5:

如果我要按学生姓名分组并用逗号分隔科目和成绩,我会怎么做?

   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

我想要一个像上面这样的数据框。

问题6:

如果我要完全融化我的数据框,所有列都作为值,我会怎么做?

     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

我想要一个像上面这样的数据框。所有列作为值。

请检查下面我的自我回答:)

pandas 版本 : 我会用df.melt(...)对于我的例子,但你需要使用pd.melt(df, ...)反而。

文档参考:

这里的大多数解决方案将与melt https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.melt.html,所以要知道方法melt https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.melt.html, see 文档解释 https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.melt.html.

将 DataFrame 从宽格式逆透视为长格式,可选择保留 标识符集。

此函数可用于将 DataFrame 转换为一种格式,其中 或多列是标识符变量(id_vars),而所有其他 列,考虑测量变量(值变量),是“未旋转的” 到行轴,只留下两个非标识符列,“变量” 和‘价值’。

参数

  • id_vars : 元组、列表或 ndarray,可选

    用作标识符变量的列。

  • 值变量 : 元组、列表或 ndarray,可选

    要取消透视的列。如果未指定,则使用未设置为 id_vars 的所有列。

  • var_name : scalar

    用于“变量”列的名称。如果没有,则使用frame.columns.name或“variable”。

  • 值名称 : 标量,默认“值”

    用于“值”列的名称。

  • 列级 : int 或 str,可选

    如果列是多重索引,则使用此级别来融化。

  • 忽略索引 : 布尔值,默认 True

    如果为 True,则忽略原始索引。如果为 False,则保留原始索引。索引标签会重复 有必要的。

    1.1.0 版本中的新增内容。

熔化逻辑:

Melting合并多列并将数据框从宽转为长,对于问题1的解决方案(见下文),步骤是:

  1. 首先我们得到原始数据框。

  2. 然后熔体首先合并Math and English列并使数据框复制(更长)。

  3. 最后它添加了列Subject这是该主题的Grades列值分别为:

这就是简单的逻辑melt函数确实如此。

解决方案:

我会解决我自己的问题。

问题一:

问题1可以用以下方法解决pd.DataFrame.melt https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.melt.html使用以下代码:

print(df.melt(id_vars=['Name', 'Age'], var_name='Subject', value_name='Grades'))

这段代码通过了id_vars论证['Name', 'Age'],然后自动将value_vars将被设置为其他列(['Math', 'English']),转换为该格式。

您还可以使用以下方法解决问题 1stack https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.stack.html像下面这样:

print(
    df.set_index(["Name", "Age"])
    .stack()
    .reset_index(name="Grade")
    .rename(columns={"level_2": "Subject"})
    .sort_values("Subject")
    .reset_index(drop=True)
)

这段代码设置了Name and Age列作为索引并堆叠其余列Math and English,并重置索引并分配Grade作为列名,然后重命名另一列level_2 to Subject然后按Subject列,然后最后再次重置索引。

这两个解决方案都会输出:

    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 https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.stack.html与列规格:

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 https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.melt.html and groupby https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.groupby.html, 使用agg功能与', '.join,如下所示:

print(
    df.melt(id_vars=["Name", "Age"])
    .groupby("value", as_index=False)
    .agg(", ".join)
)

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

stack https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.stack.html也可以用来解决这个问题,stack https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.stack.html and groupby https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.groupby.html像下面这样:

print(
    df.set_index(["Name", "Age"])
    .stack()
    .reset_index()
    .rename(columns={"level_2": "Subjects", 0: "Grade"})
    .groupby("Grade", as_index=False)
    .agg(", ".join)
)

This stack https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.stack.html函数只是以相当于的方式转置数据帧melt https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.melt.html,然后重置索引,重命名列、组和聚合。

两种解决方案输出:

  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:

我们首先融化输入数据的数据框:

df = df.melt(id_vars=['Name', 'Age'], var_name='Subject', value_name='Grades')


那么现在我们可以开始解决问题4了。

问题4可以这样解决pivot_table https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.pivot_table.html,我们必须指定pivot_table https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.pivot_table.html论据,values, index, columns并且aggfunc.

我们可以用下面的代码来解决:

print(
    df.pivot_table("Grades", ["Name", "Age"], "Subject", aggfunc="first")
    .reset_index()
    .rename_axis(columns=None)
)

Output:

   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 https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.melt.html and groupby https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.groupby.html像下面这样:

print(
    df.melt(id_vars=["Name", "Age"], var_name="Subject", value_name="Grades")
    .groupby("Name", as_index=False)
    .agg(", ".join)
)

融化并分组Name.

或者你可以stack https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.stack.html:

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 https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.melt.html并且不需要指定列,只需指定预期的列名称:

print(df.melt(var_name='Column', value_name='Value'))

这会融化整个数据框。

或者你可以stack https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.stack.html:

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

结论:

melt https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.melt.html是一个非常方便的功能,而且经常是必需的。一旦遇到这些类型的问题,不要忘记尝试melt https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.melt.html。它可能很好地解决你的问题。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何融化 pandas 数据框? 的相关文章

随机推荐