Pertimbangkan contoh sederhana ini

import pandas as pd

df = pd.DataFrame({'one' : [1,2,3],
                   'two' : [1,0,0]})

df 
Out[9]: 
   one  two
0    1    1
1    2    0
2    3    0

Saya ingin menulis fungsi yang mengambil dataframe df sebagai input dan kolom mycol.

Sekarang ini berfungsi:

df.groupby('one').two.sum()
Out[10]: 
one
1    1
2    0
3    0
Name: two, dtype: int64

Ini juga berfungsi:

 def okidoki(df,mycol):
    return df.groupby('one')[mycol].sum()

okidoki(df, 'two')
Out[11]: 
one
1    1
2    0
3    0
Name: two, dtype: int64

Tapi ini GAGAL

def megabug(df,mycol):
    return df.groupby('one').mycol.sum()

megabug(df, 'two')
 AttributeError: 'DataFrameGroupBy' object has no attribute 'mycol'

Apa yang salah di sini?

Saya khawatir okidoki menggunakan beberapa rantai yang mungkin membuat beberapa bug halus (https://pandas.pydata.org/pandas-docs/stable/indexing.html#why-does-assignment- fail-when-using-chained-indexing).

Bagaimana saya masih bisa mempertahankan sintaks groupby('one').mycol? Bisakah string mycol dikonversi menjadi sesuatu yang mungkin berfungsi seperti itu? Terima kasih!

3
ℕʘʘḆḽḘ 28 Agustus 2017, 17:37

2 jawaban

Jawaban Terbaik

Anda melewatkan string sebagai argumen kedua. Akibatnya, Anda mencoba melakukan sesuatu seperti:

df.'two'

Yang merupakan sintaks tidak valid. Jika Anda mencoba mengakses kolom secara dinamis, Anda harus menggunakan notasi indeks, [...] karena notasi pengakses titik/atribut tidak berfungsi untuk akses dinamis.


Akses dinamis sendiri dimungkinkan. Misalnya, Anda dapat menggunakan getattr (tetapi saya tidak merekomendasikan ini, ini adalah antipola):

In [674]: df
Out[674]: 
   one  two
0    1    1
1    2    0
2    3    0

In [675]: getattr(df, 'one')
Out[675]: 
0    1
1    2
2    3
Name: one, dtype: int64

Memilih secara dinamis berdasarkan atribut dari panggilan groupby dapat dilakukan, seperti:

In [677]: getattr(df.groupby('one'), mycol).sum() 
Out[677]: 
one
1    1
2    0
3    0
Name: two, dtype: int64

Tapi jangan melakukannya. Ini adalah pola anti yang mengerikan, dan jauh lebih tidak terbaca daripada df.groupby('one')[mycol].sum().

4
cs95 28 Agustus 2017, 14:45

Saya pikir Anda perlu [] untuk memilih kolom dengan nama kolom apa solusi umum untuk memilih kolom, karena pilih berdasarkan atribut memiliki banyak pengecualian:

  • Anda dapat menggunakan akses ini hanya jika elemen indeks adalah pengidentifikasi python yang valid, mis. s.1 tidak diperbolehkan. Lihat di sini untuk penjelasan tentang pengidentifikasi yang valid.
  • Atribut tidak akan tersedia jika bertentangan dengan nama metode yang ada, mis. s.min tidak diperbolehkan.
  • Demikian pula, atribut tidak akan tersedia jika bertentangan dengan salah satu daftar berikut: indeks, sumbu_utama, sumbu_kecil, item, label.
  • Dalam semua kasus ini, pengindeksan standar akan tetap berfungsi, mis. s['1'], s['min'], dan s['index'] akan mengakses elemen atau kolom yang sesuai.
def megabug(df,mycol):
    return df.groupby('one')[mycol].sum()

print (megabug(df, 'two'))

one
1    1
2    0
3    0
Name: two, dtype: int64
3
jezrael 28 Agustus 2017, 14:45