Pandas: API: Tentukan API untuk panda yang merencanakan backend

Dibuat pada 9 Jun 2019  ·  44Komentar  ·  Sumber: pandas-dev/pandas

Di #26414 kami membagi modul plotting panda menjadi kerangka kerja ploting umum yang dapat memanggil backend yang berbeda dan backend matplotlib saat ini. Idenya adalah bahwa backend lain dapat diimplementasikan dengan cara yang lebih sederhana, dan digunakan dengan API umum oleh pengguna pandas.

API yang ditentukan oleh backend matplotlib saat ini menyertakan objek yang tercantum berikutnya, tetapi API ini mungkin dapat disederhanakan. Berikut adalah daftar dengan pertanyaan/proposal:

Metode non-kontroversial untuk disimpan di API (Mereka menyediakan fungsionalitas Series.plot(kind='line') ...):

  • Garis Plot
  • BarPlot
  • BarhPlot
  • HistPlot
  • KotakPlot
  • KdePlot
  • AreaPlot
  • Plot Pai
  • Plot Tersebar
  • HexBinPlot

Fungsi plot yang disediakan di panda (misalnya pandas.plotting.andrews_curves(df) )

  • andrews_curves
  • autokorelasi_plot
  • bootstrap_plot
  • lag_plot
  • paralel_koordinat
  • radviz
  • scatter_matrix
  • meja

Haruskah itu menjadi bagian dari API dan backend lain juga harus mengimplementasikannya? Apakah masuk akal untuk mengonversi ke format .plot (misalnya DataFrame.plot(kind='autocorrelation') ...)? Apakah masuk akal untuk keluar dari API, atau pindah ke modul pihak ketiga?

Metode berlebihan yang mungkin dapat dihapus:

  • hist_series
  • hist_frame
  • petak kotak
  • boxplot_frame
  • boxplot_frame_groupoleh

Dalam kasus boxplot , saat ini kami memiliki beberapa cara untuk menghasilkan plot (terutama memanggil kode yang sama):

  1. DataFrame.plot.boxplot()
  2. DataFrame.plot(kind='box')
  3. DataFrame.boxplot()
  4. pandas.plotting.boxplot(df)

Secara pribadi, saya akan mencela nomor 4, dan untuk nomor 3, mencela atau setidaknya tidak memerlukan metode boxplot_frame di backend, tetapi coba gunakan kembali BoxPlot (untuk komentar nomor 3, sama berlaku untuk hist ).

Untuk boxplot_frame_groupby , tidak memeriksa secara detail, tetapi tidak yakin apakah BoxPlot dapat digunakan kembali untuk ini?

Fungsi untuk mendaftarkan konverter:

  • daftar
  • membatalkan pendaftaran

Apakah itu masuk akal untuk backend lain?

Tidak digunakan lagi di pandas 0.23, untuk dihapus:

  • tsplot

Untuk melihat apa yang dilakukan masing-masing fungsi ini dalam praktik, mungkin bermanfaat notebook ini oleh @liirusuk : https://github.com/python-sprints/pandas_plotting_library/blob/master/AllPlottingExamples.ipynb

CC: @pandas-dev/pandas-core @tacaswell , @jakevdp , @philippjfr , @PatrikHlobil

API Design Clean Needs Discussion Visualization

Komentar yang paling membantu

Inilah implementasi berbasis titik masuk

diff --git a/pandas/plotting/_core.py b/pandas/plotting/_core.py
index 0610780ed..c8ac12901 100644
--- a/pandas/plotting/_core.py
+++ b/pandas/plotting/_core.py
@@ -1532,8 +1532,10 @@ class PlotAccessor(PandasObject):

         return self(kind="hexbin", x=x, y=y, C=C, **kwargs)

+_backends = {}

-def _get_plot_backend(backend=None):
+
+def _get_plot_backend(backend="matplotlib"):
     """
     Return the plotting backend to use (e.g. `pandas.plotting._matplotlib`).

@@ -1546,7 +1548,14 @@ def _get_plot_backend(backend=None):
     The backend is imported lazily, as matplotlib is a soft dependency, and
     pandas can be used without it being installed.
     """
-    backend_str = backend or pandas.get_option("plotting.backend")
-    if backend_str == "matplotlib":
-        backend_str = "pandas.plotting._matplotlib"
-    return importlib.import_module(backend_str)
+    import pkg_resources  # slow import. Delay
+    if backend in _backends:
+        return _backends[backend]
+
+    for entry_point in pkg_resources.iter_entry_points("pandas_plotting_backends"):
+        _backends[entry_point.name] = entry_point.load()
+
+    try:
+        return _backends[backend]
+    except KeyError:
+        raise ValueError("No backend {}".format(backend))
diff --git a/setup.py b/setup.py
index 53e12da53..d2c6b18b8 100755
--- a/setup.py
+++ b/setup.py
@@ -830,5 +830,10 @@ setup(
             "hypothesis>=3.58",
         ]
     },
+    entry_points={
+        "pandas_plotting_backends": [
+            "matplotlib = pandas:plotting._matplotlib",
+        ],
+    },
     **setuptools_kwargs
 )

Saya pikir itu cukup bagus. Paket pihak ketiga akan memodifikasi setup.py (atau pyproject.toml) mereka untuk menyertakan sesuatu seperti

entry_points={
    "pandas_plotting_backends": ["altair = pdvega._pandas_plotting_backend"]
}

Saya suka itu mematahkan ikatan erat antara penamaan dan implementasi.

Semua 44 komentar

Saya pikir jauhkan hal-hal seperti autokorelasi dari API backend yang dapat ditukar.

Saya pikir kami telah meninggalkan hal-hal seperti df.boxplot dan hist karena mereka memiliki perilaku yang sedikit berbeda dari .plot API. Saya tidak akan merekomendasikan menjadikannya bagian dari API backend.

Inilah permulaan saya pada API backend yang diusulkan dari beberapa bulan yang lalu: https://github.com/TomAugspurger/pandas/commit/b07aba28a37b0291fd96a1f571848a7be2b6de8d

Saya pikir perlu disebutkan bahwa setidaknya hvplot (tidak memeriksa sisanya) sudah menyediakan fungsi seperti andrews_curves , scatter_matrix , lag_plot ,. ..

Mungkin jika kita tidak ingin memaksa semua backend untuk mengimplementasikannya, kita dapat memeriksa apakah backend yang dipilih mengimplementasikannya, dan default ke plot matplotlib?

Saya berasumsi boxplot dan hist berperilaku persis sama, tetapi hanya memiliki pintasan Series.hist() untuk Series.plot.hist() . "Pintasan" menunjukkan kisi plot, tetapi selain itu saya belum melihat perbedaan apa pun.

IMO, nilai utama dari opsi ini adalah ruang nama .plot .

Jika pengguna menginginkan plot kurva Andrew hvplot, mereka harus mengimpor fungsinya
dari hvplot dan berikan kerangka data di sana.

Pada Minggu, 9 Jun 2019 pukul 07.17 Marc Garcia [email protected] menulis:

Saya pikir perlu disebutkan bahwa setidaknya hvplot (tidak memeriksa
rest) sudah menyediakan fungsi seperti andrews_curves,
scatter_matrix, lag_plot,...

Mungkin jika kita tidak ingin memaksa semua backend untuk mengimplementasikannya, kita bisa
periksa apakah backend yang dipilih mengimplementasikannya, dan default ke
plot matplotlib?

Saya berasumsi boxplot dan hist berperilaku persis sama, tetapi baru saja
pintasan Series.hist() untuk Series.plot.hist(). "Jalan pintas" menunjukkan
plot grid, tetapi selain itu saya belum melihat perbedaan apa pun.


Anda menerima ini karena Anda berada di tim yang disebutkan.
Balas email ini secara langsung, lihat di GitHub
https://github.com/pandas-dev/pandas/issues/26747?email_source=notifications&email_token=AAKAOIRLJHBMXMXKK2IG2NDPZTYFPA5CNFSM4HWIMEK2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVX2ZLOIIYW76#HJKTDN5YW76
atau matikan utasnya
https://github.com/notifications/unsubscribe-auth/AAKAOISDHL6H7PVOOJAQXELPZTYFPANCNFSM4HWIMEKQ
.

Saya pikir itu masuk akal, tetapi jika kita melakukannya, saya pikir kita harus memindahkannya ke pandas.plotting.matplotlib.andrews_curves , alih-alih pandas.plotting.andrews_curves .

@TomAugspurger Saya perlu memeriksa lebih detail, tapi saya pikir API yang Anda terapkan di https://github.com/TomAugspurger/pandas/commit/b07aba28a37b0291fd96a1f571848a7be2b6de8d adalah yang lebih masuk akal. Saya akan mengerjakannya setelah saya menyelesaikan #26753. Saya juga akan bereksperimen apakah mungkin untuk memindahkan andrews_curves , scatter_matrix ... ke sintaks .plot() , saya pikir itu akan membuat segalanya lebih sederhana dan lebih mudah bagi semua orang (kami , perpustakaan pihak ketiga, dan pengguna).

Apa niatnya di sini tentang kwargs ekstra yang diteruskan ke fungsi plot? Haruskah backend tambahan mencoba untuk menduplikasi fungsionalitas dari semua penyesuaian plot gaya matplotlib, atau haruskah mereka mengizinkan kata kunci diteruskan yang sesuai dengan yang digunakan oleh backend tertentu?

Opsi pertama akan bagus secara teori, tetapi akan mengharuskan setiap backend plot non-matplotlib untuk pada dasarnya mengimplementasikan lapisan konversi matplotlibnya sendiri dengan ekor panjang yang tidak kompatibel yang pada dasarnya tidak akan pernah lengkap (berbicara dari pengalaman sebagai seseorang yang mencoba membuat mpld3 beberapa tahun yang lalu).

Opsi kedua tidak sebaik dari perspektif pertukaran, tetapi akan memungkinkan backend lain ditambahkan dengan serangkaian harapan yang lebih masuk akal.

Saya pikir itu terserah backend tentang apa yang mereka lakukan dengan mereka. mencapai 100%
kompatibilitas di seluruh backend tidak benar-benar layak,
karena tipe pengembalian tidak akan menjadi sumbu matplotlib lagi. Dan jika
kami tidak kompatibel pada tipe pengembalian, saya tidak berpikir backend
harus berusaha sekuat tenaga untuk mencoba menangani setiap argumen kata kunci yang mungkin.

Jadi saya pikir panda harus mendokumentasikan bahwa **kwargs akan diteruskan ke
mesin plot yang mendasarinya, dan mereka dapat melakukan apa pun yang mereka inginkan
mereka.

Pada Senin, 10 Jun 2019 pukul 10:42 Jake Vanderplas [email protected]
menulis:

Apa niatnya di sini tentang kwarg ekstra yang diteruskan ke plot?
fungsi? Jika backend tambahan mencoba untuk menduplikasi
fungsionalitas dari semua kustomisasi plot gaya matplotlib, atau haruskah mereka
memungkinkan kata kunci diteruskan yang sesuai dengan yang digunakan oleh yang tertentu
backend?

Opsi pertama akan bagus secara teori, tetapi akan membutuhkan setiap
non-matplotlib merencanakan backend untuk pada dasarnya mengimplementasikan matplotlibnya sendiri
lapisan konversi dengan ekor panjang yang tidak kompatibel yang akan
dasarnya tidak pernah lengkap (berbicara dari pengalaman sebagai seseorang yang
mencoba membuat mpld3 beberapa tahun yang lalu).

Pilihan kedua tidak sebaik dari sudut pandang
dipertukarkan, tetapi akan memungkinkan backend lain ditambahkan dengan lebih banyak
seperangkat harapan yang masuk akal.


Anda menerima ini karena Anda disebutkan.
Balas email ini secara langsung, lihat di GitHub
https://github.com/pandas-dev/pandas/issues/26747?email_source=notifications&email_token=AAKAOIS3IBV4XSSY7BPSCF3PZZY5LA5CNFSM4HWIMEK2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW65ZKLOORH4WSVBW63LNMVXH
atau matikan utasnya
https://github.com/notifications/unsubscribe-auth/AAKAOIQ3GYOGAPUZ4LSNK2DPZZY5LANCNFSM4HWIMEKQ
.

Saya minta maaf jika ini adalah pertanyaan bodoh, tetapi Jika Anda mendefinisikan "API" plot yang pada dasarnya adalah sekelompok plot kalengan, bukankah setiap backend akan menghasilkan output yang kurang lebih sama? kemampuan baru apa yang dimaksudkan untuk diaktifkan? sesuatu seperti pengekspor panda ke vega mungkin?

Saya tidak berpikir itu benar untuk mengatakan bahwa setiap backend menghasilkan output yang kurang lebih sama.

Misalnya, matplotlib sangat bagus dalam bagan statis, tetapi tidak hebat dalam menghasilkan bagan interaktif portabel.

Di sisi lain, bokeh, altair, dkk. bagus untuk bagan interaktif, tetapi tidak cukup matang seperti matplotlib untuk bagan statis.

Mampu menghasilkan keduanya dengan API yang sama akan menjadi kemenangan besar.

Opsi pertama akan bagus secara teori, tetapi akan mengharuskan setiap backend plot non-matplotlib untuk pada dasarnya mengimplementasikan lapisan konversi matplotlibnya sendiri dengan ekor panjang yang tidak kompatibel yang pada dasarnya tidak akan pernah lengkap (berbicara dari pengalaman sebagai seseorang yang mencoba membuat mpld3 beberapa tahun yang lalu).

dan juga menyematkan Matplotlib lebih dari yang kami miliki dalam hal API. Saya pikir masuk akal bagi panda untuk mendeklarasikan kenop gaya apa yang ingin diekspos dan mengharapkan implementasi backend untuk memilah apa artinya itu. Ini mungkin berarti _not_ secara membabi buta melewati **kwargs dan sebagai gantinya memastikan bahwa objek yang dikembalikan adalah "hal yang benar" untuk backend yang diberikan untuk dapat melakukan penyesuaian gaya setelah fakta.

Misalnya, matplotlib sangat bagus dalam bagan statis, tetapi tidak hebat dalam menghasilkan bagan interaktif portabel.

Terima kasih @jakevdp , ya, mendukung grafik interaktif adalah tujuan yang baik.

Sebelum semuanya berjalan terlalu jauh ke jalan khusus ini, inilah solusi alternatif.

Alih-alih menyatakan panda plotting API sekarang menjadi spesifikasi, dan meminta paket yaitu untuk mengimplementasikannya secara khusus, mengapa tidak membuat representasi perantara (seperti file vega JSON) dari plot, dan mendorong backend untuk menargetkan itu sebagai input mereka.

Keuntungan meliputi:

  1. Tidak terikat pada kekuatan ekspresif dari API pandas yang disempurnakan, yang tidak dirancang sebagai spesifikasi.
  2. Pekerjaan yang dilakukan dengan merencanakan paket untuk mendukung panda, menjadi tersedia untuk paket pydata lain yang menghasilkan IR.
  3. Mempromosikan bahasa umum untuk visualisasi pertukaran di ruang pydata
  4. Yang membuat alat baru lebih kuat karena lebih banyak diterapkan
  5. Yang membuat upaya menulisnya lebih masuk akal. Pada dasarnya, peningkatan insentif.

Vega/Vega-lite , sebagai bahasa spesifikasi yang modern, mapan, terbuka, dan berbasis JSON, beberapa tahun memasukkannya ke dalam desain dan implementasinya, dan alat yang ada dibangun di sekitarnya, sepertinya dibuat secara khusus untuk tujuan ini . (hanya tolong jangan ).

Anda tahu, frontend->IR->backend , seperti kompiler dirancang.

Setidaknya tiga paket sudah mengimplementasikan API. Yang perlu dilakukan panda hanyalah menawarkan opsi untuk mengubah backend dan mendokumentasikan penggunaannya, yang sepertinya sangat menguntungkan.

Pada 15 Juni 2019, pukul 16:28, pilkibun [email protected] menulis:

Misalnya, matplotlib sangat bagus dalam bagan statis, tetapi tidak hebat dalam menghasilkan bagan interaktif portabel.

Terima kasih @jakevdp , ya, mendukung grafik interaktif adalah tujuan yang baik.

Sebelum semuanya berjalan terlalu jauh ke jalan khusus ini, inilah solusi alternatif.

Alih-alih menyatakan panda plotting API sekarang menjadi spesifikasi, dan meminta paket yaitu untuk mengimplementasikannya secara khusus, mengapa tidak membuat representasi perantara (seperti file vega JSON) dari plot, dan mendorong backend untuk menargetkan itu sebagai input mereka.

Keuntungan meliputi:

Tidak terikat pada kekuatan ekspresif dari API pandas yang disempurnakan, yang tidak dirancang sebagai spesifikasi.
Pekerjaan yang dilakukan dengan merencanakan paket untuk mendukung panda, menjadi tersedia untuk paket pydata lain yang menghasilkan IR.
Mempromosikan bahasa umum untuk visualisasi pertukaran di ruang pydata
Yang membuat alat baru lebih kuat karena lebih banyak diterapkan
Yang membuat upaya menulisnya lebih masuk akal. Pada dasarnya, peningkatan insentif.
Vega/Vega-lite, sebagai bahasa spesifikasi yang modern, mapan, terbuka, dan berbasis JSON, beberapa tahun telah memasukkannya ke dalam desain dan implementasinya, dan alat yang ada dibangun di sekitarnya, sepertinya dibuat dengan jelas untuk tujuan ini . (hanya tolong jangan).

Anda tahu, frontend->IR->backend, seperti kompiler dirancang.


Anda menerima ini karena Anda disebutkan.
Balas email ini secara langsung, lihat di GitHub, atau matikan utasnya.

Kami sekarang menggabungkan #26753, dan backend plot dapat diubah dari pandas. Ketika kami membagi kode matplotlib, kami meninggalkan SeriesPlotMethods dan FramePlotMethods di sisi pandas (bukan matplotlib). Itu terutama untuk meninggalkan docstrings di sisi panda.

Tetapi saya melihat bahwa apa yang dilakukan backend adalah mengimplementasikan kembali kelas-kelas itu. Jadi, saat ini kami mengharapkan backend memiliki satu kelas per plot (misalnya LinePlot , BarPlot ), tetapi sebaliknya mereka mengimplementasikan kelas dengan plot per metode (misalnya hvPlot, or the same names as pandas for pdvega `).

Apa yang menurut saya masuk akal, setidaknya sebagai versi pertama, adalah kami mengimplementasikan API seperti yang dilakukan hvplot dan pdvega . Saya baru saja membuat kelas abstrak di panda, yang diwarisi dari backend.

Jika itu masuk akal untuk semua orang, saya akan mulai dengan membuat kelas abstrak dan mengadaptasi backend matplotlib yang kita miliki di panda, dan setelah ini selesai, kita mengadaptasi hvplot dan pdvega (perubahan harus ada cukup kecil).

Pikiran?

Apa yang menurut saya masuk akal, setidaknya sebagai versi pertama, adalah kami mengimplementasikan API seperti yang dilakukan hvplot dan pdvega. Saya baru saja membuat kelas abstrak di panda, yang diwarisi dari backend.

Saya pikir secara seimbang pendekatan ini akan lebih bersih. Saya tidak dapat berbicara dengan backend plot lainnya tetapi setidaknya di hvPlot metode plot yang berbeda berbagi sedikit kode, misalnya scatter , line dan area sebagian besar analog, dan Saya lebih suka untuk tidak bergantung pada subkelas untuk berbagi kode di antara mereka. Selain itu, saya pikir backend yang berbeda harus memiliki opsi untuk menambahkan tipe plot tambahan dan mengeksposnya sebagai metode publik tambahan sepertinya pendekatan paling sederhana dan paling alami.

Hanya untuk memastikan saya mengerti, ketika Anda mengatakan I'd prefer not to rely on subclassing to share code between them maksud Anda seperti di class LinePlot(MPLPlot) , bukan? Dan bukankah menurut Anda itu ide yang buruk untuk mewarisi dari kelas dasar abstrak?

Saya pikir saya memberi +1 dalam membiarkan backend menentukan tipe plot bukan di panda. Tapi saya mungkin tidak akan menerapkannya sekarang. Kami berencana untuk melepaskan panda dalam waktu sekitar satu minggu. Dan saya pikir ini akan membutuhkan sedikit lebih banyak pemikiran daripada secara membabi buta memanggil metode backend jika pengguna menyediakan kind='foo' dan backend menyediakan metode foo (misalnya, validasi parameter, atau itu akan menyebabkan bahwa beberapa kind akan ada dalam dokumentasi dan beberapa tidak).

Hanya untuk memastikan saya mengerti, ketika Anda mengatakan saya lebih suka untuk tidak bergantung pada subclassing untuk berbagi kode di antara mereka, maksud Anda seperti di kelas LinePlot(MPLPlot), bukan? Dan bukankah menurut Anda itu ide yang buruk untuk mewarisi dari kelas dasar abstrak?

Ya itu betul. Lebih konkretnya saya lebih suka tidak harus melakukan hal semacam ini:

class MPL1dPlot(MPLPlot):

    def _some_shared_method(self, ...):
        ...

class LinePlot(MPL1dPlot):
    ...

class AreaPlot(MPL1dPlot):
    ...

Maaf jika itu tidak jelas.

Sangat mendukung API sederhana yang diekspos secara publik sebagai fungsi tunggal alih-alih kelas seperti yang sekarang diusulkan di https://github.com/pandas-dev/pandas/pull/27009.

Pertanyaan/komentar umum tentang cara kerja opsi backend sekarang. Asumsikan saya adalah pengembang pdvega dan membuat backend ini tersedia. Itu berarti bahwa jika pengguna melakukan pd.options.plotting.backend = 'pdvega' , bahwa perpustakaan pdvega perlu memiliki fungsi plot ?
1) sebagai penulis perpustakaan, itu belum tentu fungsi yang ingin Anda tampilkan secara publik (artinya, untuk metode plot tingkat atas dari sudut pandang perpustakaan, itu belum tentu API yang Anda inginkan untuk pengguna Anda untuk digunakan secara langsung) dan 2) untuk kasus ini Anda mungkin benar-benar ingin dapat melakukan pd.options.plotting.backend = 'altair' ? (kalau-kalau pengembang altair setuju dengan itu)
Jadi pada dasarnya pertanyaan saya adalah: apakah perlu ada pemetaan 1: 1 yang tepat pada nama backend dan apa yang diimpor? (yang sekarang diperlukan karena hanya mengimpor string backend yang disediakan).

EDIT: Saya melihat bahwa sebenarnya sesuatu yang serupa dibahas di PR #26753

Jika kita membuat keputusan bahwa panda tidak tahu/membatasi backend mana yang dapat digunakan (yang sangat saya sukai), kita perlu memutuskan bagaimana/apa yang harus dipanggil di backend.

Apa yang telah diterapkan dan diusulkan dalam PR yang sedang saya kerjakan adalah opsi plotting.backend adalah modul (bisa berupa pdvega , altair , altair.pandas , atau apa pun), dan modul itu harus memiliki fungsi plot publik, itulah yang akan kita panggil.

Kita dapat mempertimbangkan opsi lain, seperti jika opsinya adalah pdvega , kita mengimpor pdvega.pandas , atau kita dapat memberi nama fungsi plot_pandas atau apa pun. Menurut saya cara yang diusulkan adalah yang paling sederhana, tetapi jika ada usulan lain yang lebih masuk akal, saya dengan senang hati mengubahnya.

Diskusi lain adalah jika kita ingin memaksa pengguna untuk mengimpor backend secara manual:

import pandas
import hvplot

pandas.Series([1, 2, 3]).plot()

Jika kita melakukannya, modul dapat mendaftarkan dirinya sendiri, mereka juga dapat mendaftarkan alias (sehingga set_option dapat memahami nama lain selain nama modul). Mereka juga dapat mengimplementasikan fungsi atau mesin khusus (misalnya manajer konteks) untuk diplot dengan backend tertentu,... Secara pribadi saya pikir semakin sederhana kita menyimpannya, semakin baik.

Dan meskipun mungkin menyenangkan melakukan pandas.set_option('plotting.backend', 'bokeh') untuk membuat plot dalam bokeh, menurut saya itu menyiratkan dua hal yang saya pribadi tidak suka:

  • pandas.set_option('plotting.backend', 'bokeh') hanya akan berfungsi jika import pandas_bokeh telah dipanggil, dan akan membingungkan pengguna.
  • Ini juga menyiratkan bahwa hanya ada satu modul untuk diplot di bokeh . Yang tidak harus benar, dan memberikan kesan yang salah kepada pengguna bahwa Anda sedang merencanakan secara langsung dengan bokeh, dan bukan dengan panda yang merencanakan backend untuk bokeh.

@datapythonista terima kasih atas jawaban terperincinya. Saya baik-baik saja dengan menyimpannya sekarang seperti untuk rilis awal (kemungkinan untuk alias selalu dapat ditambahkan nanti).

Jika pengguna menginginkan plot kurva Andrew hvplot, mereka harus mengimpor fungsi dari hvplot dan meneruskan kerangka data di sana.

+1, saya juga tidak akan mengekspos semua fungsi plot tambahan melalui backend.

Tetapi tentang memindahkannya ke pandas.plotting.matplotlib , itu tampak seperti jeda yang tidak kompatibel ke belakang yang tidak perlu bagi saya (dengan asumsi Anda bermaksud tidak hanya memindahkan implementasinya).

pandas.set_option('plotting.backend', 'bokeh') hanya akan berfungsi jika import pandas_bokeh telah dipanggil, dan akan membingungkan pengguna.

Jika kita menggunakan titik masuk untuk mendaftarkan ekstensi, maka hal ini tidak harus terjadi: menginstal paket pada sistem akan mendaftarkan titik masuk dan membuatnya terlihat oleh panda. Misalnya, inilah yang digunakan Altair untuk mendeteksi berbagai perender yang mungkin telah diinstal pengguna.

Juga, untuk apa nilainya, setelah ini masuk, saya pikir saya mungkin akan menghentikan pdvega dan memindahkan kode yang relevan ke paket baru bernama pandas_altair atau yang serupa.

@datapythonista Saya pikir kita harus memutuskan tentang ruang lingkup plotting backend API sebelum 0.25.0 (bukan untuk RC).

Anda mendukung untuk mempertahankan fungsi plot lain (serta hist / boxplot)?

@datapythonista tutup ini saat kami menggabungkan PR?

@jreback Saya akan tetap membuka ini sampai kami menyetujui API, @TomAugspurger dan @jorisvandenbossche tidak ingin mendelegasikan apa pun ke backend kecuali plot

Apa yang akan saya lakukan untuk merencanakan panda - backend adalah yang berikutnya.

Untuk rilis:

  • Biarkan semuanya apa adanya, hvplot mengimplementasikan semua plot, yang dari pengakses dan yang tidak. Dan saya hal mendelegasikan semuanya membuat segalanya tetap sederhana.
  • Tidak yakin apakah saya akan mengecualikan dari register_converters. Setidaknya kita harus mengubah nama dari register_matplotlib_converters apakah kita mendelegasikannya

Untuk rilis berikutnya:

  • Saya akan menghentikan semua duplikat pandas.plotting.boxplot , Series.hist ,...
  • Saya akan memindahkan semua plot yang akan dipanggil dari pengakses (andrew_curves, radviz, parallel_curves,...).

Untuk rilis awal API backend, saya lebih suka lebih konservatif dalam apa yang kami paparkan, daripada memasukkan semuanya. Jauh lebih mudah untuk menambahkan sesuatu nanti, daripada menghapusnya.

Saya pribadi juga tidak akan memindahkan semua plot misc ke accessor (mungkin ada beberapa pengecualian, seperti matriks pencar), IMO andrew_curves dan radviz dll tidak "layak" metode.

Yang mengatakan: apakah kita ingin mengizinkan backend untuk mengimplementasikan "jenis" tambahan? Jadi kita tidak perlu memutuskan, sebagai panda, metode pengakses mana yang tersedia. Jika pengguna melewati kind atau mencoba mengakses atribut, kami masih dapat meneruskannya ke backend plot dengan __getattribute__ kustom.

Hanya untuk menjelaskan sedikit mengapa hal-hal seperti sekarang. Ini relevan karena saya tidak yakin bagaimana menerapkan perubahan yang Anda usulkan, atau tidak mengungkapkan hal-hal secara umum. Tidak mengatakan di sini bahwa itu tidak dapat dilakukan dengan cara yang berbeda, itu hanya untuk memperkaya diskusi.

Keputusan pertama adalah memindahkan semua kode menggunakan matplotlib ke modul terpisah ( pandas.plotting._matplotlib ). Dengan melakukan itu, modul itu entah bagaimana menjadi backend matplotlib.

Segala sesuatu yang bersifat publik di pandas.plotting telah disimpan sebagai publik di sana. Dan untuk membuat segalanya sesederhana mungkin, setiap fungsi ini, setelah dipanggil, akan memuat backend (panggil ke _get_plot_backend ) dan memanggil fungsi di sana.

API publik untuk pengguna tidak ada perubahan sama sekali, pengguna masih memiliki metode dan fungsi yang sama. Kami tidak mengekspos sesuatu yang baru.

Bagaimana saya memahami banyak hal, jika kami memutuskan bahwa plot yang ada seperti andrew_curves tidak didelegasikan ke backend, artinya ini adalah bahwa alih-alih mendapatkan backend yang dipilih oleh pengguna, kami masih akan memilih backend matplotlib. Mengingat bahwa setidaknya hvplot sudah menerapkan andrew_curves , saya pribadi tidak mengerti maksudnya. Jika pengguna menginginkan plot andrew_curves di matplotlib semudah tidak mengubah backend (atau mengaturnya lagi jika sudah diubah). Jadi, dengan perubahan yang kami lakukan hanyalah membuat hidup pengguna jauh lebih sulit, dengan menambahkan kerumitan ekstra pada panda.

Jika kita ingin bersikap baik dengan pengembang backend dan tidak memaksa mereka untuk mengimplementasikan plot yang mungkin tidak begitu umum (saya kira itu salah satu alasannya?), mungkin kita dapat default ke matplotlib backend apa pun yang hilang di backend yang dipilih ?

Tentang mendelegasikan jenis plot yang tidak diketahui ke backend, saya sedang melakukannya sekarang. Tentunya itu bisa masuk akal pada akhirnya. Tapi saya pikir memiliki beberapa jenis plot yang didokumentasikan dalam panda, dan memiliki plot tambahan yang tidak kami dokumentasikan, terasa sedikit rumit. Saya pikir itu bisa menunggu versi berikutnya, setelah kami mendapat umpan balik tentang cara kerja backend yang berbeda untuk pengguna, dan kami memiliki lebih banyak waktu untuk berdiskusi dan menganalisis secara mendetail.

Jika pengguna menginginkan plot andrew_curves di matplotlib semudah tidak mengubah backend (atau mengaturnya lagi jika sudah diubah). Jadi, dengan perubahan yang kami lakukan hanyalah membuat hidup pengguna jauh lebih sulit, dengan menambahkan kerumitan ekstra pada panda.

Saya tidak berpikir kami akan membuat hidup pengguna lebih sulit. Alih-alih mengimpornya dari pandas.plotting, jika mereka menginginkan versi hvplot, mereka cukup mengimpornya dari sana. Yang merupakan sesuatu yang tidak mungkin untuk metode DataFrame.plot, seperti yang didefinisikan pada objek. Bagi saya itu adalah alasan utama untuk merencanakan backend.

Jika kita ingin bersikap baik dengan pengembang backend dan tidak memaksa mereka untuk mengimplementasikan plot yang mungkin tidak terlalu mainstream

Bagi saya ini bukan tentang bersikap baik atau bahwa mengimplementasikan semuanya akan diperlukan (tidak apa-apa jika backend tidak mendukung semua jenis plot, IMO), melainkan perluasan yang tidak perlu dari API backend plot, yang juga mengikat diri kita sendiri untuk itu .
Jika kita akan memulai kembali panda dari awal, saya rasa tipe plot lain itu tidak akan disertakan. Tetapi dengan API backend yang memplot, kami dalam beberapa hal memulai sesuatu yang baru.

Ada pendapat lain tentang ini?

Setuju dengan @jorisvandenbossche.


Hanya untuk memastikan ini tidak hilang, saya pikir saran @ jakevdp untuk menggunakan titik masuk setuptool layak dipertimbangkan untuk menyelesaikan masalah pendaftaran pesanan impor: https://github.com/pandas-dev/pandas/issues/26747 #issuecomment -507415929

@jorisvandenbossche bagaimana Anda mengubahnya dalam kode? Alih-alih mendapatkan backend yang ditentukan dalam pengaturan untuk metode tersebut, dapatkan backend matplotlib? Saya pikir ini salah secara konseptual, tapi saya setuju jika ada kesepakatan. Apa pun yang mengembalikan decoupling kode matplotlib dari yang lain, I'm -1.

Karena Anda menyebutkan bahwa dalam panda dari awal, kami tidak akan menyertakan plot itu, haruskah kami mencelanya? Saya memberi +1 untuk memindahkan semua plot yang bukan metode Series atau DataFrame ke paket pihak ketiga. Atau jika ada yang cukup penting untuk disimpan, untuk dipindahkan disebut dengan .plot() seperti yang lainnya.

saya akan mencela plot non standar di panda
dan pindah ke paket eksternal

Joris sedang offline sebentar.

Saya pikir ketika kita telah membahas ini di masa lalu, posisinya dan posisi saya pada tesis adalah membiarkannya tidak tersentuh sampai menjadi beban pemeliharaan.

Jadi kita berada di halaman yang sama, ini adalah ringkasan dari apa yang kita miliki, dan pemahaman saya tentang keadaan diskusi:

Digunakan sebagai metode Series dan DataFrame (afaik kami semua senang mempertahankannya apa adanya, didelegasikan ke backend yang dipilih):

  • PlotAccessor
  • boxplot_frame
  • boxplot_frame_groupoleh
  • hist_frame
  • hist_series

Plot lain (dalam diskusi apakah harus ditinggalkan, didelegasikan ke backend matplotlib, atau didelegasikan ke backend yang dipilih):

  • petak kotak
  • scatter_matrix
  • radviz
  • andrews_curves
  • bootstrap_plot
  • paralel_koordinat
  • lag_plot
  • autokorelasi_plot
  • meja

Barang publik lainnya di pandas.plotting (sedang didiskusikan juga):

  • plot_params
  • register_matplotlib_converters
  • deregister_matplotlib_converters

Untuk bagian Other plots , saya pribadi berpikir mereka adalah beban pemeliharaan pada saat ini, dan saya memberi +1 untuk memindahkannya dari panda, dan mencelanya di 0.25.

Untuk konverter dan hal-hal lain, apa yang kita miliki sekarang pasti tidak benar, karena register_matplotlib_converters mendelegasikan ke plot yang dipilih, yang tidak dapat menjadi matplotlib. Opsi yang menurut saya dapat kita pertimbangkan adalah:

  • Ganti nama mereka menjadi register_converters / deregister_converters , hentikan yang saat ini, dan terus delegasikan ke backend
  • Pindahkan dari pandas.plotting ke pandas.plotting.matplotlib (yang berarti membuat backend matplotlib menjadi publik, jadi saya tidak akan melakukannya)
  • Biarkan mereka apa adanya, dan delegasikan ke backend matplotlib alih-alih backend yang dipilih (Saya melihat ini lebih sebagai peretasan daripada keputusan desain yang baik, saya lebih suka menjaga pandas.plotting agnostik dari backend mana yang ada)

Untuk bagian Plot lainnya, saya pribadi menganggapnya sebagai beban pemeliharaan pada saat ini, dan saya memberi +1 untuk memindahkannya dari panda, dan mencelanya di 0.25.

Bagaimana Anda menemukan "petak lain" menjadi beban pemeliharaan? Melihat riwayat plot "lain-lain": https://github.com/pandas-dev/pandas/commits/0.24.x/pandas/plotting/_misc.py , kami memiliki ~10-15 komit sejak 2017. mayoritas adalah pembersihan global yang diterapkan ke seluruh basis kode (jadi beban marjinal kecil). Saya hanya melihat 1-2 komit mengubah dokumen, dan tidak ada komit yang mengubah fungsionalitas.

Ganti nama mereka menjadi register_converters/deregister_converters, hentikan yang sekarang, dan tetap mendelegasikan ke backend

Saya tidak berpikir ini akan masuk akal. Ada konverter khusus matplotlib yang telah kami tulis untuk matplotlib. Backend lain tidak akan memilikinya. Mungkin seharusnya tidak menjadi bagian dari API backend.

Saya tidak bermaksud bahwa plot itu menjadi beban karena jumlah pemeliharaan yang kami dapatkan dalam beberapa bulan terakhir tahun, tetapi karena masalah yang mereka duga sekarang dalam memiliki API yang konsisten dan intuitif untuk pengguna, dan modul yang bagus desain kode untuk kami.

Mengenai konverter, saya tidak tahu apakah penulis backend mungkin ingin menerapkan yang setara dengan yang untuk matplotlib dalam beberapa kasus. Tetapi sepertinya tidak masalah jika tidak, dan fungsi-fungsi itu tidak melakukan apa pun untuk beberapa atau semua backend lainnya. Saya juga setuju dengan opsi 2, tetapi saya tidak menganggapnya rapi.

tetapi karena masalah yang mereka duga sekarang dalam memiliki API yang konsisten dan intuitif untuk pengguna, dan desain kode modular yang baik untuk kami.

Mereka sudah agak tidak konsisten dengan DataFrame.plot. Nama "misc" menyiratkan bahwa :) Apakah memiliki backend yang dapat ditukar memperburuknya? Sejauh itu sepadan dengan churn pada kode pengguna? Saya tidak berpikir begitu.

Saya tidak tahu apakah penulis backend mungkin ingin menerapkan yang setara dengan yang untuk matplotlib dalam beberapa kasus.

Saya tidak berpikir begitu. Maksud dari konverter itu adalah untuk mengajarkan matplotlib tentang objek panda. Perpustakaan yang mengimplementasikan backend tidak akan mengalami masalah itu, karena mereka sudah bergantung pada panda.

Secara pribadi saya memikirkannya terutama dalam hal mengelola kompleksitas. Memiliki API plot standar yang didelegasikan ke backend melalui satu API mudah dipahami, dan dipelihara. Pengguna dan pengelola hanya perlu mengetahui bahwa ada fungsi plot dengan argumen kind , dan ini akan dieksekusi di backend yang dipilih.

Memiliki di backend satu set plot heterogen, yang selain tidak mengikuti API yang sama, gunakan backend, tetapi bukan yang dipilih untuk plot lain, tetapi yang Matplotlib, menambah terlalu banyak kerumitan untuk semua orang IMHO.

Dan biaya untuk memindahkannya tampak kecil bagi saya, dugaan saya adalah bahwa tidak banyak pengguna kami yang tahu tentang plot tersebut. Dan bagi yang melakukannya, mereka hanya perlu menginstal paket conda tambahan dan menggunakan import pandas_plotting; pandas_plotting.andrews_curves(df) alih-alih pandas.plotting.andrews_curves(df) .

Bagi saya tampaknya banyak menang, dengan biaya kecil, tapi tentu saja itu hanya pendapat.

Bisakah kita mendokumentasikan bahwa backend yang dapat ditukar hanya untuk Series/DataFrame.plot? Itu sepertinya aturan yang cukup sederhana.

Terasa seperti peretasan yang menambah kerumitan yang tidak perlu bagi saya; Saya tidak berpikir menjelaskannya dalam dokumentasi membuatnya kurang kontra-intuitif.

Tapi bagaimanapun, bukan masalah besar. Jika itu opsi yang disukai, beginilah cara saya mengimplementasikannya, setidaknya peningkatan kompleksitas kode minimal: #27432

Melihat lebih dekat pada ini sekarang: jika saya mengerti dengan benar, cara plotting backend akan diatur menggunakan:

pd.set_option('plotting.backend', 'name_of_module')

Pemahaman saya, kemudian, adalah bahwa jika saya ingin membuat pekerjaan berikut:

pd.set_option('plotting.backend', 'altair')

maka saya akan memerlukan paket altair tingkat atas untuk mendefinisikan semua fungsi di https://github.com/pandas-dev/pandas/blob/master/pandas/plotting/_core.py . Saya lebih suka untuk tidak mencemari namespace tingkat atas Altair dengan semua API tambahan ini yang tidak dimaksudkan untuk benar-benar digunakan oleh pengguna Altair. Sebenarnya, saya lebih suka ekstensi pandas altair untuk hidup dalam paket terpisah, jadi itu tidak terikat dengan irama rilis Altair itu sendiri.

Jika saya mengerti dengan benar, ini berarti bahwa tidak ada cara bagi saya untuk membuat pd.set_option('plotting.backend', 'altair') bekerja dengan benar tanpa hard-coding paket altair di pandas cara matplotlib saat ini hard-coded, apakah itu benar?

https://github.com/pandas-dev/pandas/blob/f1b9fc1fab93caa59aebcc738eed7813d9bd92ee/pandas/plotting/_core.py#L1550 -L1551

Jika demikian, saya sangat menyarankan untuk memikirkan kembali cara API ini diekspos dalam paket pihak ketiga.

Solusi yang saya sarankan adalah dengan mengadopsi kerangka kerja berbasis titik masuk yang memungkinkan saya, misalnya, membuat paket seperti altair_pandas yang mendaftarkan titik masuk altair untuk mengimplementasikan API. Jika tidak, pengguna akan selamanya bingung bahwa pd.set_option('plotting.backend', 'altair') tidak melakukan apa yang mereka harapkan.

Sepakat. Saya pikir titik masuk adalah cara untuk pergi. Saya akan membuat prototipe sesuatu.

Pada Jum, 19 Juli 2019 pukul 13:16 Jake Vanderplas [email protected]
menulis:

Melihat lebih dekat pada ini sekarang: jika saya mengerti dengan benar, cara itu
backend ploting akan diatur menggunakan:

pd.set_option('plotting.backend', 'name_of_module')

Pemahaman saya, kemudian, adalah bahwa jika saya ingin membuat pekerjaan berikut:

pd.set_option('plotting.backend', 'altair')

maka saya akan membutuhkan paket altair tingkat atas untuk mendefinisikan semua fungsi
di dalam
https://github.com/pandas-dev/pandas/blob/master/pandas/plotting/_core.py.
Saya lebih suka untuk tidak mencemari namespace tingkat atas Altair dengan semua ini
API tambahan. Sebenarnya, saya lebih suka ekstensi panda Altair ke
hidup dalam paket terpisah, jadi tidak terikat dengan irama rilis
Altair sendiri.

Jika saya mengerti dengan benar, ini berarti tidak ada cara bagi saya untuk membuat pd.set_option('plotting.backend',
'altair') bekerja dengan benar tanpa hard-coding paket altair di panda
cara matplotlib saat ini dikodekan dengan keras, apakah itu benar?

Jika demikian, saya sangat menyarankan untuk memikirkan kembali bagaimana ini diaktifkan oleh
paket pihak ketiga. Secara khusus, mengadopsi kerangka kerja berbasis titik masuk
akan membiarkan saya membuat paket seperti altair_pandas yang mendaftarkan altair
titik masuk. Jika tidak, pengguna akan selamanya bingung bahwa pd.set_option('plotting.backend',
'altair') tidak melakukan apa yang mereka harapkan.


Anda menerima ini karena Anda disebutkan.
Balas email ini secara langsung, lihat di GitHub
https://github.com/pandas-dev/pandas/issues/26747?email_source=notifications&email_token=AAKAOITQM7HH5X4SZ4IAPS3QAIAIBA5CNFSM4HWIMEK2YY3PNVWWK3TUL52HS4DFVREXG43VMVBWQ278DN5MLWWZQ268DN5MLWWZQ278DN5MLVXH2
atau matikan utasnya
https://github.com/notifications/unsubscribe-auth/AAKAOISFLHDGXLGQ3PUMNLDQAIAIBANCNFSM4HWIMEKQ
.

Ada titik waktu di mana apa yang Anda katakan sebagian besar benar, tapi itu tidak terjadi lagi.

Jika Anda ingin pandas.options.plotting.backend = 'altair' , di 0.25 Anda hanya perlu memiliki fungsi altair.plot() . Pada titik tertentu saya pikir akan lebih baik untuk memanggil fungsi pandas_plot daripada hanya plot , jadi itu spesifik di backend yang memiliki hal-hal lain, tetapi kami akhirnya tidak membuat perubahan.

Jika membuat fungsi plot di tingkat atas altair adalah masalah, kami dapat mengganti namanya di versi mendatang, atau Anda juga dapat memiliki altair.pandas.plot , tetapi pengguna harus menyetel pandas.options.plotting.backend = 'altair.pandas' .

Anda pasti dapat mengubah opsi sendiri setelah pengguna melakukan import altair . Dan kami dapat menerapkan registri backend. Tetapi saya pikir akan membingungkan pengguna jika mereka melakukan pandas.options.plotting.backend = 'altair' dan gagal, karena mereka lupa import altair sebelumnya.

Satu hal terakhir adalah untuk mempertimbangkan bahwa kita mungkin dapat memiliki lebih dari satu backend panda yang diimplementasikan untuk altair (atau perpustakaan visualisasi lainnya). Jadi, bagi saya, bahwa nama backend bukan altair , belum tentu merupakan hal yang buruk.

Inilah implementasi berbasis titik masuk

diff --git a/pandas/plotting/_core.py b/pandas/plotting/_core.py
index 0610780ed..c8ac12901 100644
--- a/pandas/plotting/_core.py
+++ b/pandas/plotting/_core.py
@@ -1532,8 +1532,10 @@ class PlotAccessor(PandasObject):

         return self(kind="hexbin", x=x, y=y, C=C, **kwargs)

+_backends = {}

-def _get_plot_backend(backend=None):
+
+def _get_plot_backend(backend="matplotlib"):
     """
     Return the plotting backend to use (e.g. `pandas.plotting._matplotlib`).

@@ -1546,7 +1548,14 @@ def _get_plot_backend(backend=None):
     The backend is imported lazily, as matplotlib is a soft dependency, and
     pandas can be used without it being installed.
     """
-    backend_str = backend or pandas.get_option("plotting.backend")
-    if backend_str == "matplotlib":
-        backend_str = "pandas.plotting._matplotlib"
-    return importlib.import_module(backend_str)
+    import pkg_resources  # slow import. Delay
+    if backend in _backends:
+        return _backends[backend]
+
+    for entry_point in pkg_resources.iter_entry_points("pandas_plotting_backends"):
+        _backends[entry_point.name] = entry_point.load()
+
+    try:
+        return _backends[backend]
+    except KeyError:
+        raise ValueError("No backend {}".format(backend))
diff --git a/setup.py b/setup.py
index 53e12da53..d2c6b18b8 100755
--- a/setup.py
+++ b/setup.py
@@ -830,5 +830,10 @@ setup(
             "hypothesis>=3.58",
         ]
     },
+    entry_points={
+        "pandas_plotting_backends": [
+            "matplotlib = pandas:plotting._matplotlib",
+        ],
+    },
     **setuptools_kwargs
 )

Saya pikir itu cukup bagus. Paket pihak ketiga akan memodifikasi setup.py (atau pyproject.toml) mereka untuk menyertakan sesuatu seperti

entry_points={
    "pandas_plotting_backends": ["altair = pdvega._pandas_plotting_backend"]
}

Saya suka itu mematahkan ikatan erat antara penamaan dan implementasi.

Saya tidak bekerja dengan titik masuk, apakah mereka seperti registri global lingkungan Python? Menjadi baru bagi mereka, saya tidak menyukai ide itu, tetapi saya kira itu akan menjadi cara yang masuk akal untuk melakukannya.

Saya masih ingin memiliki kedua opsi, jadi jika pengguna melakukan pandas.options.plottting.backend = 'my_own_project.my_custom_small_backend' itu berfungsi, dan tidak perlu membuat paket, dan mengatur titik masuk.

Saya tidak bekerja dengan titik masuk, apakah mereka seperti registri global lingkungan Python?

Saya juga belum menggunakannya, tapi saya pikir itulah idenya. Dari apa yang saya pahami, mereka berasal dari setuptools (tetapi paket seperti flit hook ke dalamnya?). Jadi mereka bukan bagian dari perpustakaan standar, tetapi setuptools adalah yang digunakan semua orang.

Saya masih ingin memiliki kedua opsi

Kembali ke import_module(backend_name) tampaknya masuk akal.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat