gpt4 book ai didi

python - 如何融化 Pandas 数据框?

转载 作者:行者123 更新时间:2023-12-04 11:47:03 25 4
gpt4 key购买 nike

关于 标签,我经常看到用户询问有关在 Pandas 中融合数据框的问题。我将尝试针对此主题进行规范的问答(自我回答)。
我要澄清:

  • 什么是熔体?
  • 我如何使用熔体?
  • 我什么时候使用熔体?

  • 我看到一些关于融化的热门问题,例如:
  • pandas convert some columns into rows : 这个其实还可以,不过多解释一下会更好。
  • Pandas Melt Function : nice question answer很好,但是有点太含糊了,没有太多的解释。
  • Melting a pandas dataframe : 也不错的回答!但这仅适用于那种非常简单的特定情况,只有 pd.melt(df)
  • Pandas dataframe use columns as rows (melt) : 非常整洁!但问题是它仅针对 OP 提出的特定问题,这也是使用 pivot_table 所必需的。以及。

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

    数据集:
    我将在这个随机成绩数据集上为随机年龄的随机人提供我所有的答案(更容易解释答案: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
    >>>
    问题:
    我会遇到一些问题,它们将在我下面的自我回答中得到解决。
    问题1:
    如何融化数据帧,使原始数据帧变为:
        Name  Age  Subject Grade
    0 Bob 13 English C
    1 John 16 English B
    2 Foo 14 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 14 Math A
    9 Bar 15 Math F
    10 Alex 17 Math D
    11 Tom 12 Math C
    我想将其转置,以便一列是每个主题,而其他列将是学生的重复姓名以及年龄和分数。
    问题2:
    这个和问题1类似,但是这次我要让问题1输出 Subject栏目只有 Math ,我想过滤掉 English柱子:
       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:
    我将如何解开融化的数据框?假设我已经融化了这个数据框:
    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 版本低于 0.20.0 的用户请注意,我将使用 df.melt(...)对于我的示例,但您的版本对于 df.melt 来说太低了,您需要使用 pd.melt(df, ...)反而。
    文档引用:
    这里的大多数解决方案都将与 melt 一起使用,所以要知道方法 melt ,见 documentaion解释

    Unpivot a DataFrame from wide to long format, optionally leavingidentifiers set.

    This function is useful to massage a DataFrame into a format where oneor more columns are identifier variables (id_vars), while all othercolumns, considered measured variables (value_vars), are “unpivoted”to the row axis, leaving just two non-identifier columns, ‘variable’and ‘value’.


    参数是:

    Parameters

    • id_vars : tuple, list, or ndarray, optional

      Column(s) to use as identifier variables.

    • value_vars : tuple, list, or ndarray, optional

      Column(s) to unpivot. If not specified, uses all columns that are not set as id_vars.

    • var_name : scalar

      Name to use for the ‘variable’ column. If None it uses frame.columns.name or ‘variable’.

    • value_namescalar, default ‘value’

      Name to use for the ‘value’ column.

    • col_level : int or str, optional

      If columns are a MultiIndex then use this level to melt.

    • ignore_index : bool, default True

      If True, original index is ignored. If False, the original index is retained. Index labels will be repeatedas necessary.

      New in version 1.1.0.


    熔化的逻辑:
    Melting合并多列并将dataframe从宽转换为长,对于问题1的解决方案(见下文),步骤是:
  • 首先我们得到了原始数据框。
  • 然后熔体首先合并MathEnglish列并复制数据帧(更长)。
  • 然后最后添加列Subject这是 Grades 的主题列值分别。


  • 这是 melt 的简单逻辑功能确实。
    解决方案:
    我会解决我自己的问题。
    问题1:
    问题 1 可以使用 pd.DataFrame.melt 解决使用以下代码:
    print(df.melt(id_vars=['Name', 'Age'], var_name='Subject', value_name='Grades'))
    此代码通过 id_vars论据 ['Name', 'Age'] ,然后自动 value_vars将设置为其他列( ['Math', 'English'] ),该列被转置为该格式。
    您也可以使用 stack 解决问题 1像下面这样:
    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_2Subject然后按 Subject 排序列,然后最终再次重置索引。
    这两种解决方案都输出:
        Name  Age  Subject Grade
    0 Bob 13 English C
    1 John 16 English B
    2 Foo 14 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 14 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 也可以用 stack 来解决这个问题和 groupby 像下面这样:
    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:
    我们首先融化输入数据的数据框:
    df = df.melt(id_vars=['Name', 'Age'], var_name='Subject', value_name='Grades')

    那么现在我们可以开始解决这个问题4了。
    问题 4 可以用 pivot_table 解决,我们必须指定 pivot_table 参数, values , index , columns还有 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 :
    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 :
    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 是一个非常方便的功能,经常需要,一旦你遇到这些类型的问题,不要忘记尝试 melt ,它可以很好地解决您的问题。
    请记住,对于 Pandas 版本低于 0.20.0 的用户,您必须使用 pd.melt(df, ...)而不是 df.melt(...) .

    关于python - 如何融化 Pandas 数据框?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68961796/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com