首頁  >  文章  >  後端開發  >  如何融化 pandas 資料框?

如何融化 pandas 資料框?

WBOY
WBOY轉載
2024-02-09 23:30:14394瀏覽

如何融化 pandas 数据框?

問題內容

在 pandas 標籤上,我經常看到用戶詢問有關在 pandas 中融化資料幀的問題。我將嘗試針對這個主題進行規範的問答(自我回答)。

我要澄清:

  1. 什麼是熔化?

  2. 如何使用melt?

  3. 什麼時候使用melt?

我看到一些有關融化的熱門問題,例如:

  • 使用 pandas 將列轉換為行:這個實際上可能很好,但更多的解釋會更好。

  • pandas melt function:一個很好的問題,答案也很好,但有點太模糊了,沒有太多解釋。

  • 融化 pandas 資料框:也是一個很好的答案!但這只是針對特定情況,這很簡單,只有 pd.melt(df)

  • pandas 資料框使用列作為行(融化):非常整潔!但問題是,它只針對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   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列:

   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:

我如何解凍一個熔化的資料框?假設我已經融化了這個資料框:

df = 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(... ) 作為我的範例,但您需要使用pd.melt(df, .. .) 來代替。

文件參考:

這裡的大多數解決方案都會與melt,所以要知道方法melt ,請參閱文檔說明

熔化邏輯:

melting合併多列,將dataframe由寬轉長,解決問題1(見下文),步驟為:

  1. 首先我們得到了原始資料幀。

  2. 然後,melt 首先合併 mathenglish 列,並使資料幀複製(更長)。

  3. 最後它加入了 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_2phpcnendcphp cn 到<code>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 与列规格:

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

以上是如何融化 pandas 資料框?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:stackoverflow.com。如有侵權,請聯絡admin@php.cn刪除