Bagaimana untuk mencairkan bingkai data panda?

WBOY
Lepaskan: 2024-02-09 23:30:14
ke hadapan
392 orang telah melayarinya

如何融化 pandas 数据框?

Isi soalan

Pada tag panda, saya sering melihat pengguna bertanya soalan tentang mencairkan bingkai data dalam panda. Saya akan cuba melakukan Soal Jawab (jawapan sendiri) kanonik mengenai topik ini.

Saya ingin menjelaskan:

  1. Apa itu mencair?

  2. Bagaimana cara menggunakan melt?

  3. Bila nak guna melt?

Saya melihat beberapa soalan popular tentang lebur, seperti:

  • Tukar lajur kepada baris menggunakan panda: Yang ini sebenarnya mungkin bagus, tetapi lebih baik penjelasannya.

  • fungsi panda cair: Soalan yang bagus dengan jawapan yang baik, tetapi agak terlalu kabur tanpa banyak penjelasan.

  • Bingkai data panda cair: Juga jawapan yang bagus! Tetapi itu hanya untuk kes tertentu, ia mudah, hanya pd.melt(df)

  • bingkai data panda menggunakan lajur sebagai baris (cair) : Sangat kemas! Tetapi masalahnya, ia hanya menangani soalan khusus yang ditanya oleh OP, yang juga memerlukan penggunaan pivot_table.

Jadi saya akan cuba buat Soal Jawab berkanun mengenai topik ini.

Set data:

Saya akan menemui semua jawapan dalam set data gred rawak ini untuk orang rawak pada usia rawak (lebih mudah untuk menerangkan jawapannya :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]})
Salin selepas log masuk
>>> 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
Salin selepas log masuk

Soalan:

Soalan 1:

Bagaimana untuk mencairkan kerangka data supaya kerangka data asal menjadi seperti berikut?

    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
Salin selepas log masuk
Salin selepas log masuk

Saya ingin mengubahnya supaya satu lajur untuk setiap mata pelajaran dan lajur yang lain adalah nama berulang pelajar berserta umur dan markah mereka.

Soalan 2:

Ini serupa dengan soalan 1, tetapi kali ini saya mahu soalan 1 dikeluarkan subject列只有math,我想过滤掉englishlajur:

   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
Salin selepas log masuk

Saya mahu output kelihatan seperti di atas.

Soalan 3:

Sekiranya saya mengumpulkan leburan dan menyusunnya mengikut markah pelajar, bagaimana saya akan melakukannya untuk mendapatkan output yang diingini seperti ini:

  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
Salin selepas log masuk

Saya perlu mengisihnya dengan nama yang dipisahkan dengan koma dan subjects dipisahkan dengan koma dalam susunan yang sama.

Soalan 4:

Bagaimana cara saya menyah beku bingkai data cair? Katakan saya telah mencairkan kerangka data ini:

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

Menjadi:

    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
Salin selepas log masuk

Jadi bagaimana cara saya menukarnya kembali kepada bingkai data asal seperti yang ditunjukkan di bawah?

   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
Salin selepas log masuk

Soalan 5:

Apakah yang akan saya lakukan jika saya ingin mengumpulkan pelajar mengikut nama dan mengasingkan mata pelajaran dan gred dengan koma?

   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
Salin selepas log masuk

Saya mahukan dataframe seperti di atas.

Soalan 6:

Jika saya mencairkan sepenuhnya bingkai data saya dengan semua lajur sebagai nilai, apakah yang akan saya lakukan?

     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
Salin selepas log masuk

Saya mahukan dataframe seperti di atas. Semua lajur sebagai nilai.


Jawapan betul


Nota untuk versi panda < 0.20.0 : Saya akan menggunakan df.melt(...) 作为我的示例,但您需要使用 pd.melt(df, .. .) sebaliknya.

Rujukan dokumen:

Kebanyakan penyelesaian di sini akan berfungsi dengan melt< 一起使用/a>,所以要知道方法melt, jadi untuk mengetahui caranya sila lihat

arahan dokumentasi

.

Logik Lebur:

    Melting menggabungkan berbilang lajur, menukar bingkai data daripada lebar kepada panjang dan menyelesaikan masalah 1 (lihat di bawah langkah-langkahnya ialah:
  1. ).

  2. Mula-mula kita dapat bingkai data asal.
  3. mathenglish

    Kemudian cair mencantumkan
  4. lajur terlebih dahulu dan menjadikan rangka data diduplikasi (lebih lama).
  5. subject 列,它分别是 grades

    Akhirnya ia menambah
  6. tema untuk nilai lajur:

melt

Ini adalah logik mudah fungsi

.

Penyelesaian:

Soalan 1: pd.dataframe.meltMasalah 1 boleh diselesaikan menggunakan

menggunakan kod berikut: id_vars 参数传递给 ['name', 'age'],然后自动将 value_vars 设置为其他列(['math', 'english']

print(df.melt(id_vars=['name', 'age'], var_name='subject', value_name='grades'))
Salin selepas log masuk

Kod ini menukarkan

), iaitu transpose, ke dalam format ini. stackAnda juga boleh menggunakan

seperti di bawah: nameage 列设置为索引,并堆叠其余列 mathenglish,并重置索引并指定 grade 作为列名称,然后将其他列重命名为 level_2phpcnendcphp cn 到 <code>subject 然后按subject

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

Kod ini menetapkan lajur nama dan age sebagai indeks dan menyusun lajur yang tinggal

dan menetapkan semula indeks dan menentukan gred sebagai nama lajur, Kemudian namakan semula lajur lain kepada level_2phpcnendcphp cn kepada <code>subject kemudian tekan lajur subject dan akhirnya set semula indeks sekali lagi.

🎜Kedua-dua keluaran penyelesaian: 🎜
    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
Salin selepas log masuk
Salin selepas log masuk

问题 2:

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

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

或者我们也可以使用 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)
)
Salin selepas log masuk

这两种解决方案都给出:

   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
Salin selepas log masuk

问题 3:

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

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

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

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)
)
Salin selepas log masuk

这个 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
Salin selepas log masuk

问题 4:

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

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

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

输出:

   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
Salin selepas log masuk

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

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

问题 5:

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

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

融化并按 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)
)
Salin selepas log masuk

两个代码输出:

   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
Salin selepas log masuk

问题 6:

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

print(df.melt(var_name='column', value_name='value'))
Salin selepas log masuk

这会融化整个数据框。

或者您可以stack

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

两个代码输出:

     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
Salin selepas log masuk

Atas ialah kandungan terperinci Bagaimana untuk mencairkan bingkai data panda?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:stackoverflow.com
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan
Tentang kita Penafian Sitemap
Laman web PHP Cina:Latihan PHP dalam talian kebajikan awam,Bantu pelajar PHP berkembang dengan cepat!