clj-python / libpython-clj

Python bindings for Clojure
Eclipse Public License 2.0
1.05k stars 68 forks source link

Question: How to call plot.hist, post.line etc methods on a pandas Series ? #210

Closed thecontinium closed 1 year ago

thecontinium commented 2 years ago

Hi

Thanks for writing this library.

I am trying to call a method on a pandas Series object to produce a plot for various kinds of graphs. I have this working when using plot alone but I can't find a way of invoking the plot.hist, plot.line, etc methods.

This works fine for different :kind's:

(def pandas-series (pandas/Series [1 2 3]))
(py. pandas-series "plot" :kind :hist)

but I want to call the plot.hist method. This fails:

(def pandas-series (pandas/Series [1 2 3]))
 (py. pandas-series "plot.hist") ; ==> (err) AttributeError: 'Series' object has no attribute 'plot.hist'

If I do this I find that the plot.hist is a PlotAccessor.hist

(def plot (py/get-attr pandas/Series "plot")) 
(py/get-attr plot "hist") ; ==> <function PlotAccessor.hist at 0x16666c560>

But how do I call this method on the pandas-series ?

All advice welcome - Thanks.

cnuernber commented 2 years ago

Perhaps py.. will work - (py.. pandas-series plot hist).

Probably the return value of (py/get-attr plot "hist") is callable. This means you can use it like a clojure function and you can also use call-attr, call-attr-kw on the plot object depending on if you want keyword arguments.

cnuernber commented 1 year ago

py.. solves this. I do not have matplotlib installed but you can see it called the method:

user> (def pd (py/import-module "pandas"))
#'user/pd
user> (def s (py/py. pd Series [1 2 3]))
#'user/s
user> s
0    1
1    2
2    3
dtype: int64
user> (py/py.. s plot hist)
Execution error at libpython-clj2.python.ffi/check-error-throw (ffi.clj:708).
Traceback (most recent call last):
  File "/home/chrisn/miniconda3/lib/python3.9/site-packages/pandas/plotting/_core.py", line 892, in __call__
    plot_backend = _get_plot_backend(kwargs.pop("backend", None))
  File "/home/chrisn/miniconda3/lib/python3.9/site-packages/pandas/plotting/_core.py", line 1814, in _get_plot_backend
    module = _load_backend(backend)
  File "/home/chrisn/miniconda3/lib/python3.9/site-packages/pandas/plotting/_core.py", line 1754, in _load_backend
    raise ImportError(
ImportError: matplotlib is required for plotting when the default backend "matplotlib" is selected.