본문 바로가기
코딩/파이썬

plt.savefig 함수에서의 must be real number, not str 오류 발생

by yenua 2024. 1. 9.
반응형

아래 캐글 코드를 돌려보다가, 그래프 사진을 저장하는 코드에서 'must be real number, not str'라는 오류가 발생하였다.

# https://www.kaggle.com/code/shivamb/semi-supervised-classification-using-autoencoders/notebook
def tsne_plot(x1, y1, name="graph.png"):
    tsne = TSNE(n_components=2, random_state=0)
    X_t = tsne.fit_transform(x1)

    plt.figure(figsize=(12, 8))
    plt.scatter(X_t[np.where(y1 == 0), 0], X_t[np.where(y1 == 0), 1], marker='o', color='g', linewidth='1', alpha=0.8, label='Non Fraud')
    plt.scatter(X_t[np.where(y1 == 1), 0], X_t[np.where(y1 == 1), 1], marker='o', color='r', linewidth='1', alpha=0.8, label='Fraud')

    plt.legend(loc='best');
    plt.savefig(name);
    plt.show();
    
tsne_plot(X, Y, "original.png")

 

 

▼ 오류 로그

더보기
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-21-38294f5ed148> in <cell line: 15>()
     13     plt.show();
     14 
---> 15 tsne_plot(X, Y, "original.png")

18 frames
<ipython-input-21-38294f5ed148> in tsne_plot(x1, y1, name)
     10     print(name)
     11     print(type(name))
---> 12     plt.savefig(name);
     13     plt.show();
     14 

/usr/local/lib/python3.10/dist-packages/matplotlib/pyplot.py in savefig(*args, **kwargs)
   1021 def savefig(*args, **kwargs):
   1022     fig = gcf()
-> 1023     res = fig.savefig(*args, **kwargs)
   1024     fig.canvas.draw_idle()  # Need this if 'transparent=True', to reset colors.
   1025     return res

/usr/local/lib/python3.10/dist-packages/matplotlib/figure.py in savefig(self, fname, transparent, **kwargs)
   3341                         ax.patch._cm_set(facecolor='none', edgecolor='none'))
   3342 
-> 3343             self.canvas.print_figure(fname, **kwargs)
   3344 
   3345     def ginput(self, n=1, timeout=30, show_clicks=True,

/usr/local/lib/python3.10/dist-packages/matplotlib/backend_bases.py in print_figure(self, filename, dpi, facecolor, edgecolor, orientation, format, bbox_inches, pad_inches, bbox_extra_artists, backend, **kwargs)
   2364                 # force the figure dpi to 72), so we need to set it again here.
   2365                 with cbook._setattr_cm(self.figure, dpi=dpi):
-> 2366                     result = print_method(
   2367                         filename,
   2368                         facecolor=facecolor,

/usr/local/lib/python3.10/dist-packages/matplotlib/backend_bases.py in <lambda>(*args, **kwargs)
   2230                 "bbox_inches_restore"}
   2231             skip = optional_kws - {*inspect.signature(meth).parameters}
-> 2232             print_method = functools.wraps(meth)(lambda *args, **kwargs: meth(
   2233                 *args, **{k: v for k, v in kwargs.items() if k not in skip}))
   2234         else:  # Let third-parties do as they see fit.

/usr/local/lib/python3.10/dist-packages/matplotlib/backends/backend_agg.py in print_png(self, filename_or_obj, metadata, pil_kwargs)
    507             *metadata*, including the default 'Software' key.
    508         """
--> 509         self._print_pil(filename_or_obj, "png", pil_kwargs, metadata)
    510 
    511     def print_to_buffer(self):

/usr/local/lib/python3.10/dist-packages/matplotlib/backends/backend_agg.py in _print_pil(self, filename_or_obj, fmt, pil_kwargs, metadata)
    455         *pil_kwargs* and *metadata* are forwarded).
    456         """
--> 457         FigureCanvasAgg.draw(self)
    458         mpl.image.imsave(
    459             filename_or_obj, self.buffer_rgba(), format=fmt, origin="upper",

/usr/local/lib/python3.10/dist-packages/matplotlib/backends/backend_agg.py in draw(self)
    398              (self.toolbar._wait_cursor_for_draw_cm() if self.toolbar
    399               else nullcontext()):
--> 400             self.figure.draw(self.renderer)
    401             # A GUI class may be need to update a window using this draw, so
    402             # don't forget to call the superclass.

/usr/local/lib/python3.10/dist-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
     93     @wraps(draw)
     94     def draw_wrapper(artist, renderer, *args, **kwargs):
---> 95         result = draw(artist, renderer, *args, **kwargs)
     96         if renderer._rasterizing:
     97             renderer.stop_rasterizing()

/usr/local/lib/python3.10/dist-packages/matplotlib/artist.py in draw_wrapper(artist, renderer)
     70                 renderer.start_filter()
     71 
---> 72             return draw(artist, renderer)
     73         finally:
     74             if artist.get_agg_filter() is not None:

/usr/local/lib/python3.10/dist-packages/matplotlib/figure.py in draw(self, renderer)
   3138 
   3139             self.patch.draw(renderer)
-> 3140             mimage._draw_list_compositing_images(
   3141                 renderer, self, artists, self.suppressComposite)
   3142 

/usr/local/lib/python3.10/dist-packages/matplotlib/image.py in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
    129     if not_composite or not has_images:
    130         for a in artists:
--> 131             a.draw(renderer)
    132     else:
    133         # Composite any adjacent images together

/usr/local/lib/python3.10/dist-packages/matplotlib/artist.py in draw_wrapper(artist, renderer)
     70                 renderer.start_filter()
     71 
---> 72             return draw(artist, renderer)
     73         finally:
     74             if artist.get_agg_filter() is not None:

/usr/local/lib/python3.10/dist-packages/matplotlib/axes/_base.py in draw(self, renderer)
   3062             _draw_rasterized(self.figure, artists_rasterized, renderer)
   3063 
-> 3064         mimage._draw_list_compositing_images(
   3065             renderer, self, artists, self.figure.suppressComposite)
   3066 

/usr/local/lib/python3.10/dist-packages/matplotlib/image.py in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
    129     if not_composite or not has_images:
    130         for a in artists:
--> 131             a.draw(renderer)
    132     else:
    133         # Composite any adjacent images together

/usr/local/lib/python3.10/dist-packages/matplotlib/artist.py in draw_wrapper(artist, renderer)
     70                 renderer.start_filter()
     71 
---> 72             return draw(artist, renderer)
     73         finally:
     74             if artist.get_agg_filter() is not None:

/usr/local/lib/python3.10/dist-packages/matplotlib/collections.py in draw(self, renderer)
    970     def draw(self, renderer):
    971         self.set_sizes(self._sizes, self.figure.dpi)
--> 972         super().draw(renderer)
    973 
    974 

/usr/local/lib/python3.10/dist-packages/matplotlib/artist.py in draw_wrapper(artist, renderer)
     70                 renderer.start_filter()
     71 
---> 72             return draw(artist, renderer)
     73         finally:
     74             if artist.get_agg_filter() is not None:

/usr/local/lib/python3.10/dist-packages/matplotlib/collections.py in draw(self, renderer)
    403             gc.set_antialiased(self._antialiaseds[0])
    404             gc.set_url(self._urls[0])
--> 405             renderer.draw_markers(
    406                 gc, paths[0], combined_transform.frozen(),
    407                 mpath.Path(offsets), offset_trf, tuple(facecolors[0]))

TypeError: must be real number, not str

 

 

해결 방법은 매우 간단했다. 그저 숫자로 들어가야 할 것이 문자열로 들어갔기 때문.. name이 문제인 줄 알았는데 다른 부분이 문제였다. tsne_plot 함수의 4, 5번째 코들줄에 있는 linewidth를 지정할 때 문제가 발생했던 것이었다.

linewidth='1'이 아니라 linewidth=1을 해주어야 한다. 아니 캐글에는 왜 이렇게 되어있던거람? 스택오버플로우를 보면 이전 버전의 matplotlib에서는 문제가 되지 않았지만, 현재에는 오류가 발생하게 되는 포인트인 것 같다.

 

그래서 실행이 되는 코드는 아래와 같다.

def tsne_plot(x1, y1, name="graph.png"):
    tsne = TSNE(n_components=2, random_state=0)
    X_t = tsne.fit_transform(x1)

    plt.figure(figsize=(12, 8))
    plt.scatter(X_t[np.where(y1 == 0), 0], X_t[np.where(y1 == 0), 1], marker='o', color='g', linewidth=1, alpha=0.8, label='Non Fraud')
    plt.scatter(X_t[np.where(y1 == 1), 0], X_t[np.where(y1 == 1), 1], marker='o', color='r', linewidth=1, alpha=0.8, label='Fraud')

    plt.legend(loc='best');
    print(name)
    print(type(name))
    plt.savefig(name);
    plt.show();
    
tsne_plot(X, Y, "original.png")

 

참고: https://stackoverflow.com/questions/68090145/python-type-error-raised-during-savefig-in-matplotlib

반응형