{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "*이 노트북은 제이크 반더플라스(Jake VanderPlas)의 [A Whirlwind Tour of Python](http://www.oreilly.com/programming/free/a-whirlwind-tour-of-python.csp)(OReilly Media, 2016)를 기반으로 만들어졌습니다. 이 내용은 [CC0](https://github.com/jakevdp/WhirlwindTourOfPython/blob/master/LICENSE) 라이센스를 따릅니다. 전체 노트북의 목록은 https://github.com/rickiepark/WhirlwindTourOfPython 에서 볼 수 있습니다.*" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "< [문자열과 정규 표현식](14-문자열과 정규 표현식.ipynb) | [목차](목차.ipynb) | [더 읽을 거리](16-Further-Resources.ipynb) >" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 데이터 과학 도구 소개" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "파이썬을 과학 컴퓨팅과 데이터 과학에 사용하고 싶다면 사용가히 편리한 패키지가 여러개 있습니다. 이 절은 그 중에 중요한 몇 개를 소개하겠습니다. 여러분이 만들려고 하는 애플리케이션에 도움이 될 것입니다. *아나콘다*나 *미니콘다* 환경을 사용하고 있다면 다음 명령으로 관련 패키지를 설치할 수 있습니다:\n", "```\n", "$ conda install numpy scipy pandas matplotlib scikit-learn\n", "```\n", "차례대로 간단히 살펴보죠." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 넘파이(NumPy): 수치 파이썬(Numerical Python)\n", "\n", "넘파이는 파이썬에서 다차원 밀집(dense) 배열을 효율적으로 저장하고 조작하는 도구입니다. 넘파이의 주요 기능은 다음과 같습니다:\n", "\n", "- 베터, 행렬과 고차원 데이터셋을 효율적으로 저장하고 조작할 수 있는 ``ndarray`` 구조를 제공합니다.\n", "- 간단한 원소별 산술 연산에서부터 복잡한 선형 대수 연산까지 데이터를 조작하기 위한 명료하고 효과적인 문법을 제공합니다.\n", "\n", "가장 간단한 경우 넘파이는 파이썬의 리스트와 비슷합니다. 예를 들어 1에서 9까지 숫자를 담은 배열을 다음과 같이 만듭니다(파이썬의 내장 ``range()``와 비교해 보세요):" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([1, 2, 3, 4, 5, 6, 7, 8, 9])" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import numpy as np\n", "x = np.arange(1, 10)\n", "x" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "넘파이 배열은 데이터를 효율적으로 저장할 뿐만아니라 이 데이터에 대한 효율적인 원소별 연산을 제공합니다.\n", "예를 들어 배열의 각 원소를 거듭제곱하려면 배열에 \"``**``\" 연산자를 직접 적용할 수 있습니다:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([ 1, 4, 9, 16, 25, 36, 49, 64, 81])" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "x ** 2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "동일한 결과를 내는 파이썬의 리스트 내포와 비교해 보세요:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[1, 4, 9, 16, 25, 36, 49, 64, 81]" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "[val ** 2 for val in range(1, 10)]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "(1차원에 제한된)파이썬 리스트와는 달리 넘파이 배열은 다차원이 가능합니다.\n", "예를 들어 ``x`` 배열을 3x3 배열로 바꾸어 보겠습니다:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[1, 2, 3],\n", " [4, 5, 6],\n", " [7, 8, 9]])" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M = x.reshape((3, 3))\n", "M" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "2차원 배열은 행렬을 나타내며 넘파이는 일반적인 행렬 연산을 효율적으로 수행할 수 있습니다. 예를 들어 ``.T``를 사용해 행렬을 전치할 수 있습니다:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[1, 4, 7],\n", " [2, 5, 8],\n", " [3, 6, 9]])" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M.T" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "또는 ``np.dot``을 사용해 행렬-벡터 곱을 할 수 있습니다:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([ 38, 92, 146])" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.dot(M, [5, 6, 7])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "또는 고유값 분해 같은 더 복잡한 연산도 가능합니다:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([ 1.61168440e+01, -1.11684397e+00, -9.75918483e-16])" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.linalg.eigvals(M)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "이런 선형 대수 연산은 최신 데이터 분석, 특히 머신 러닝과 데이터 마이닝 분야에 꼭 필요합니다." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 판다스(Pandas): 레이블된 열 중심의 데이터\n", "\n", "판다스는 넘파이보다 더 최근에 등장한 패키지이고 넘파이를 사용합니다.\n", "판다스는 R 같은 언어를 사용했던 사용자들에게 친숙한 DataFrame 형태의 다차원 데이터에 레이블된 인터페이스를 제공합니다.\n", "판다스의 DataFrame은 다음과 같습니다:" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
labelvalue
0A1
1B2
2C3
3A4
4B5
5C6
\n", "
" ], "text/plain": [ " label value\n", "0 A 1\n", "1 B 2\n", "2 C 3\n", "3 A 4\n", "4 B 5\n", "5 C 6" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import pandas as pd\n", "df = pd.DataFrame({'label': ['A', 'B', 'C', 'A', 'B', 'C'],\n", " 'value': [1, 2, 3, 4, 5, 6]})\n", "df" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "판다스에서는 이름으로 열을 선택할 수 있습니다:" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0 A\n", "1 B\n", "2 C\n", "3 A\n", "4 B\n", "5 C\n", "Name: label, dtype: object" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df['label']" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "문자열 열에는 문자열 연산을 적용할 수 있습니다:" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0 a\n", "1 b\n", "2 c\n", "3 a\n", "4 b\n", "5 c\n", "Name: label, dtype: object" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df['label'].str.lower()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "숫자형 열에는 합계 메서드를 적용할 수 있습니다:" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "21" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df['value'].sum()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "그리고 가장 중요한 것은 데이터베이스 스타일의 조인(join)과 그룹핑이 가능합니다:" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
value
label
A5
B7
C9
\n", "
" ], "text/plain": [ " value\n", "label \n", "A 5\n", "B 7\n", "C 9" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.groupby('label').sum()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "이렇게 같은 레이블을 같는 모든 원소의 합을 한 줄의 코드로 계산할 수 있습니다. 넘파이나 파이썬 내장 함수를 사용하면 훨씬 번거롭고 더 비효율적입니다." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 맷플롯립(Matplotlib): 매트랩(MatLab) 스타일의 시각화\n", "\n", "맷플롯립은 현재 파이썬에서 가장 인기있는 과학 그래픽 패키지입니다.\n", "인터페이스가 좀 번거로운 것은 사실이지만 다양한 종류의 그래프를 만들 수 있는 강력한 라이브러리입니다.\n", "\n", "맷플롯립을 사용하려면 관례상 패키지를 ``plt``로 임포팅합니다." ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [], "source": [ "# 주피터 노트북에서 실행할 때 반응형 그래프를 만들어 줍니다\n", "%matplotlib notebook" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [], "source": [ "import matplotlib.pyplot as plt\n", "plt.style.use('ggplot') # R의 ggplot 스타일로 그래프를 만듭니다" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "이제 약간의 데이터를 만들어 (당연히 넘파이 배열로) 그래프를 그려 보죠:" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "application/javascript": [ "/* Put everything inside the global mpl namespace */\n", "window.mpl = {};\n", "\n", "\n", "mpl.get_websocket_type = function() {\n", " if (typeof(WebSocket) !== 'undefined') {\n", " return WebSocket;\n", " } else if (typeof(MozWebSocket) !== 'undefined') {\n", " return MozWebSocket;\n", " } else {\n", " alert('Your browser does not have WebSocket support.' +\n", " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", " 'Firefox 4 and 5 are also supported but you ' +\n", " 'have to enable WebSockets in about:config.');\n", " };\n", "}\n", "\n", "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", " this.id = figure_id;\n", "\n", " this.ws = websocket;\n", "\n", " this.supports_binary = (this.ws.binaryType != undefined);\n", "\n", " if (!this.supports_binary) {\n", " var warnings = document.getElementById(\"mpl-warnings\");\n", " if (warnings) {\n", " warnings.style.display = 'block';\n", " warnings.textContent = (\n", " \"This browser does not support binary websocket messages. \" +\n", " \"Performance may be slow.\");\n", " }\n", " }\n", "\n", " this.imageObj = new Image();\n", "\n", " this.context = undefined;\n", " this.message = undefined;\n", " this.canvas = undefined;\n", " this.rubberband_canvas = undefined;\n", " this.rubberband_context = undefined;\n", " this.format_dropdown = undefined;\n", "\n", " this.image_mode = 'full';\n", "\n", " this.root = $('
');\n", " this._root_extra_style(this.root)\n", " this.root.attr('style', 'display: inline-block');\n", "\n", " $(parent_element).append(this.root);\n", "\n", " this._init_header(this);\n", " this._init_canvas(this);\n", " this._init_toolbar(this);\n", "\n", " var fig = this;\n", "\n", " this.waiting = false;\n", "\n", " this.ws.onopen = function () {\n", " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", " fig.send_message(\"send_image_mode\", {});\n", " if (mpl.ratio != 1) {\n", " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n", " }\n", " fig.send_message(\"refresh\", {});\n", " }\n", "\n", " this.imageObj.onload = function() {\n", " if (fig.image_mode == 'full') {\n", " // Full images could contain transparency (where diff images\n", " // almost always do), so we need to clear the canvas so that\n", " // there is no ghosting.\n", " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", " }\n", " fig.context.drawImage(fig.imageObj, 0, 0);\n", " };\n", "\n", " this.imageObj.onunload = function() {\n", " fig.ws.close();\n", " }\n", "\n", " this.ws.onmessage = this._make_on_message_function(this);\n", "\n", " this.ondownload = ondownload;\n", "}\n", "\n", "mpl.figure.prototype._init_header = function() {\n", " var titlebar = $(\n", " '
');\n", " var titletext = $(\n", " '
');\n", " titlebar.append(titletext)\n", " this.root.append(titlebar);\n", " this.header = titletext[0];\n", "}\n", "\n", "\n", "\n", "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", "\n", "}\n", "\n", "\n", "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", "\n", "}\n", "\n", "mpl.figure.prototype._init_canvas = function() {\n", " var fig = this;\n", "\n", " var canvas_div = $('
');\n", "\n", " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", "\n", " function canvas_keyboard_event(event) {\n", " return fig.key_event(event, event['data']);\n", " }\n", "\n", " canvas_div.keydown('key_press', canvas_keyboard_event);\n", " canvas_div.keyup('key_release', canvas_keyboard_event);\n", " this.canvas_div = canvas_div\n", " this._canvas_extra_style(canvas_div)\n", " this.root.append(canvas_div);\n", "\n", " var canvas = $('');\n", " canvas.addClass('mpl-canvas');\n", " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", "\n", " this.canvas = canvas[0];\n", " this.context = canvas[0].getContext(\"2d\");\n", "\n", " var backingStore = this.context.backingStorePixelRatio ||\n", "\tthis.context.webkitBackingStorePixelRatio ||\n", "\tthis.context.mozBackingStorePixelRatio ||\n", "\tthis.context.msBackingStorePixelRatio ||\n", "\tthis.context.oBackingStorePixelRatio ||\n", "\tthis.context.backingStorePixelRatio || 1;\n", "\n", " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n", "\n", " var rubberband = $('');\n", " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", "\n", " var pass_mouse_events = true;\n", "\n", " canvas_div.resizable({\n", " start: function(event, ui) {\n", " pass_mouse_events = false;\n", " },\n", " resize: function(event, ui) {\n", " fig.request_resize(ui.size.width, ui.size.height);\n", " },\n", " stop: function(event, ui) {\n", " pass_mouse_events = true;\n", " fig.request_resize(ui.size.width, ui.size.height);\n", " },\n", " });\n", "\n", " function mouse_event_fn(event) {\n", " if (pass_mouse_events)\n", " return fig.mouse_event(event, event['data']);\n", " }\n", "\n", " rubberband.mousedown('button_press', mouse_event_fn);\n", " rubberband.mouseup('button_release', mouse_event_fn);\n", " // Throttle sequential mouse events to 1 every 20ms.\n", " rubberband.mousemove('motion_notify', mouse_event_fn);\n", "\n", " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", "\n", " canvas_div.on(\"wheel\", function (event) {\n", " event = event.originalEvent;\n", " event['data'] = 'scroll'\n", " if (event.deltaY < 0) {\n", " event.step = 1;\n", " } else {\n", " event.step = -1;\n", " }\n", " mouse_event_fn(event);\n", " });\n", "\n", " canvas_div.append(canvas);\n", " canvas_div.append(rubberband);\n", "\n", " this.rubberband = rubberband;\n", " this.rubberband_canvas = rubberband[0];\n", " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", " this.rubberband_context.strokeStyle = \"#000000\";\n", "\n", " this._resize_canvas = function(width, height) {\n", " // Keep the size of the canvas, canvas container, and rubber band\n", " // canvas in synch.\n", " canvas_div.css('width', width)\n", " canvas_div.css('height', height)\n", "\n", " canvas.attr('width', width * mpl.ratio);\n", " canvas.attr('height', height * mpl.ratio);\n", " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n", "\n", " rubberband.attr('width', width);\n", " rubberband.attr('height', height);\n", " }\n", "\n", " // Set the figure to an initial 600x600px, this will subsequently be updated\n", " // upon first draw.\n", " this._resize_canvas(600, 600);\n", "\n", " // Disable right mouse context menu.\n", " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", " return false;\n", " });\n", "\n", " function set_focus () {\n", " canvas.focus();\n", " canvas_div.focus();\n", " }\n", "\n", " window.setTimeout(set_focus, 100);\n", "}\n", "\n", "mpl.figure.prototype._init_toolbar = function() {\n", " var fig = this;\n", "\n", " var nav_element = $('
')\n", " nav_element.attr('style', 'width: 100%');\n", " this.root.append(nav_element);\n", "\n", " // Define a callback function for later on.\n", " function toolbar_event(event) {\n", " return fig.toolbar_button_onclick(event['data']);\n", " }\n", " function toolbar_mouse_event(event) {\n", " return fig.toolbar_button_onmouseover(event['data']);\n", " }\n", "\n", " for(var toolbar_ind in mpl.toolbar_items) {\n", " var name = mpl.toolbar_items[toolbar_ind][0];\n", " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", " var image = mpl.toolbar_items[toolbar_ind][2];\n", " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", "\n", " if (!name) {\n", " // put a spacer in here.\n", " continue;\n", " }\n", " var button = $('');\n", " button.click(method_name, toolbar_event);\n", " button.mouseover(tooltip, toolbar_mouse_event);\n", " nav_element.append(button);\n", " }\n", "\n", " // Add the status bar.\n", " var status_bar = $('');\n", " nav_element.append(status_bar);\n", " this.message = status_bar[0];\n", "\n", " // Add the close button to the window.\n", " var buttongrp = $('
');\n", " var button = $('');\n", " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", " button.mouseover('Stop Interaction', toolbar_mouse_event);\n", " buttongrp.append(button);\n", " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", " titlebar.prepend(buttongrp);\n", "}\n", "\n", "mpl.figure.prototype._root_extra_style = function(el){\n", " var fig = this\n", " el.on(\"remove\", function(){\n", "\tfig.close_ws(fig, {});\n", " });\n", "}\n", "\n", "mpl.figure.prototype._canvas_extra_style = function(el){\n", " // this is important to make the div 'focusable\n", " el.attr('tabindex', 0)\n", " // reach out to IPython and tell the keyboard manager to turn it's self\n", " // off when our div gets focus\n", "\n", " // location in version 3\n", " if (IPython.notebook.keyboard_manager) {\n", " IPython.notebook.keyboard_manager.register_events(el);\n", " }\n", " else {\n", " // location in version 2\n", " IPython.keyboard_manager.register_events(el);\n", " }\n", "\n", "}\n", "\n", "mpl.figure.prototype._key_event_extra = function(event, name) {\n", " var manager = IPython.notebook.keyboard_manager;\n", " if (!manager)\n", " manager = IPython.keyboard_manager;\n", "\n", " // Check for shift+enter\n", " if (event.shiftKey && event.which == 13) {\n", " this.canvas_div.blur();\n", " event.shiftKey = false;\n", " // Send a \"J\" for go to next cell\n", " event.which = 74;\n", " event.keyCode = 74;\n", " manager.command_mode();\n", " manager.handle_keydown(event);\n", " }\n", "}\n", "\n", "mpl.figure.prototype.handle_save = function(fig, msg) {\n", " fig.ondownload(fig, null);\n", "}\n", "\n", "\n", "mpl.find_output_cell = function(html_output) {\n", " // Return the cell and output element which can be found *uniquely* in the notebook.\n", " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", " // IPython event is triggered only after the cells have been serialised, which for\n", " // our purposes (turning an active figure into a static one), is too late.\n", " var cells = IPython.notebook.get_cells();\n", " var ncells = cells.length;\n", " for (var i=0; i= 3 moved mimebundle to data attribute of output\n", " data = data.data;\n", " }\n", " if (data['text/html'] == html_output) {\n", " return [cell, data, j];\n", " }\n", " }\n", " }\n", " }\n", "}\n", "\n", "// Register the function which deals with the matplotlib target/channel.\n", "// The kernel may be null if the page has been refreshed.\n", "if (IPython.notebook.kernel != null) {\n", " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", "}\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from scipy import interpolate\n", "\n", "# 0과 10 사이에 8개의 포인트를 선택합니다\n", "x = np.linspace(0, 10, 8)\n", "y = np.sin(x)\n", "\n", "# 세제곱 보간 함수를 만듭니다\n", "func = interpolate.interp1d(x, y, kind='cubic')\n", "\n", "# 1,000개의 포인트를 보간합니다\n", "x_interp = np.linspace(0, 10, 1000)\n", "y_interp = func(x_interp)\n", "\n", "# 보간 결과를 그래프로 출력합니다\n", "plt.figure() # 새로운 그래프\n", "plt.plot(x, y, 'o')\n", "plt.plot(x_interp, y_interp);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "8개 포인트 사이에 부드러운 보간 결과를 볼 수 있습니다." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 다른 데이터 과학 패키지\n", "\n", "이런 도구를 기반으로 많은 데이터 과학 패키지가 만들어졌습니다. 대표적으로 머신러닝을 위한 [Scikit-Learn](http://scikit-learn.org), 이미지 분석을 위한 [Scikit-Image](http://scikit-image.org), 통계적 모델링을 위한 [Statsmodels](http://statsmodels.sourceforge.net/) 등입니다. 또 천문학과 천체 물리를 위한 [AstroPy](http://astropy.org), 신경 이미지 처리를 위한 [NiPy](http://nipy.org/)와 같이 도메인에 특화된 많은 라이브러리가 있습니다.\n", "\n", "당면한 과학, 수치 또는 통계 문제가 무엇이든지 간에 아마 이를 도와줄 수 있는 파이썬 패키지가 준비되어 있을 것입니다." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "< [문자열과 정규 표현식](14-문자열과 정규 표현식.ipynb) | [목차](목차.ipynb) | [더 읽을 거리](16-Further-Resources.ipynb) >" ] } ], "metadata": { "anaconda-cloud": {}, "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.5" } }, "nbformat": 4, "nbformat_minor": 1 }