{"id":24293,"date":"2023-10-17T21:04:43","date_gmt":"2023-10-17T21:04:43","guid":{"rendered":"https:\/\/www.highcharts.com\/blog\/?p=24293"},"modified":"2026-01-13T11:36:58","modified_gmt":"2026-01-13T11:36:58","slug":"highcharts-core-python-pandas","status":"publish","type":"post","link":"https:\/\/www.highcharts.com\/blog\/integration\/highcharts-core-python-pandas\/","title":{"rendered":"Using Highcharts Core for Python with Pandas"},"content":{"rendered":"<p><a href=\"https:\/\/pandas.pydata.org\/\" target=\"_blank\" rel=\"noopener\">Pandas<\/a> is probably the single most popular library for data analysis in the Python ecosystem. Together with <a href=\"https:\/\/www.numpy.org\/\" target=\"_blank\" rel=\"noopener\">NumPy<\/a>, it is ubquitous. And the <b>Highcharts for Python Toolkit<\/b> is designed to natively integrate with it.<\/p>\n<h2>General approach<\/h2>\n<p>The <b>Highcharts for Python Toolkit<\/b> provides a number of standard methods that are used to interact with <code>pandas.DataFrame<\/code> instances. These methods generally take the form:<\/p>\n<ul>\n<li><code>.from_pandas(df)<\/code> This is always a class method which produces one or more instances, with data pulled from the df argument.<\/li>\n<li><code>.from_pandas_in_rows(df)<\/code>  This is always a class method which produces one instance for every row in the <code> DataFrame (df)<\/code>.<\/li>\n<li><code>.load_from_pandas(df)<\/code>  This is an instance method which updates an instance with data read from the <code> df<\/code>  argument.<\/li>\n<\/ul>\n<p><i><b>Tip<\/b><\/p>\n<p>All three of these standard methods are packaged to have batteries included. This means that for simple use cases, you can simply pass a <code>pandas.DataFrame<\/code> to the method, and the method wlil attempt to determine the optimum way to deserialize the <code>DataFrame<\/code> into the appropriate <b>Highcharts for Python<\/b> objects.<\/p>\n<p>However, if you find that you need more fine-grained control, the methods provide powerful tools to give you the control you need when you need it.<\/i><\/p>\n<p>These standard methods &#8211; with near-identical syntax &#8211; are available:<\/p>\n<ul>\n<li>On all series classes (descended from SeriesBase)<\/li>\n<li>On the Chart class<\/li>\n<li>On the options.data.Data class<\/li>\n<\/ul>\n<h2>Preparing your DataFrame<\/h2>\n<p><i><b>Tip<\/b><\/p>\n<p>While it is theoretically possible for <b>Highcharts for Python<\/b> to work with a nested <code>DataFrame<\/code>, such structures are generally considered an anti-pattern. We recommend keeping your <code>DataFrame<\/code> contents 2-dimensional, organized into a single \u201cflat\u201d table of rows and columns.<\/i><\/p>\n<p>So let\u2019s try a real-world example. Let\u2019s say you\u2019ve got some annual population counts stored in a CSV file named <code>'census-time-series.csv'<\/code>. Using Pandas, you can construct a DataFrame from that CSV file very simply:<\/p>\n<pre> df = pandas.read_csv('census-time-series.csv')<\/pre>\n<p>This produces a simple 2-dimensional <code>DataFrame<\/code>. In our case, the resulting table looks like this:<br \/>\n<img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2023\/10\/17192744\/census-time-series-01.jpg\" alt=\"a table with US geographic area and population from 2010 to 2019\" width=\"970\" height=\"181\" class=\"alignnone size-full wp-image-24295\" srcset=\"https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2023\/10\/17192744\/census-time-series-01.jpg 970w, https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2023\/10\/17192744\/census-time-series-01-560x104.jpg 560w, https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2023\/10\/17192744\/census-time-series-01-760x142.jpg 760w, https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2023\/10\/17192744\/census-time-series-01-768x143.jpg 768w\" sizes=\"auto, (max-width: 970px) 100vw, 970px\" \/><\/p>\n<p>The first column contains the names of geographic regions, while each of the subsequent columns contains the population counts for a given year. However, you\u2019ll notice that the <code>DataFrame<\/code> index is not set. Unless told otherwise, <b>Highcharts for Python<\/b> will look for x-axis values in the index.<\/p>\n<p>Secondly, if you were to look under the hood, you\u2019d see that the <code>DataFrame<\/code> imported all of the numbers in our CSV as strings (because of the presence of the comma), which is obviously a bit of a problem. So let\u2019s fix both of these issues:<\/p>\n<pre>df = pandas.read_csv('census-time-series.csv', index_col = 0, thousands = ','))<\/pre>\n<p>produces:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2023\/10\/17192744\/census-time-series-01.jpg\" alt=\"a table with US geographic area and ordered population from 2010 to 2019\" width=\"970\" height=\"181\" class=\"alignnone size-full wp-image-24295\" srcset=\"https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2023\/10\/17192744\/census-time-series-01.jpg 970w, https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2023\/10\/17192744\/census-time-series-01-560x104.jpg 560w, https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2023\/10\/17192744\/census-time-series-01-760x142.jpg 760w, https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2023\/10\/17192744\/census-time-series-01-768x143.jpg 768w\" sizes=\"auto, (max-width: 970px) 100vw, 970px\" \/><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2023\/10\/17193400\/census-time-series-02.jpg\" alt=\"\" width=\"887\" height=\"219\" class=\"alignnone size-full wp-image-24296\" srcset=\"https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2023\/10\/17193400\/census-time-series-02.jpg 887w, https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2023\/10\/17193400\/census-time-series-02-560x138.jpg 560w, https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2023\/10\/17193400\/census-time-series-02-760x188.jpg 760w, https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2023\/10\/17193400\/census-time-series-02-768x190.jpg 768w\" sizes=\"auto, (max-width: 887px) 100vw, 887px\" \/><\/p>\n<p>Great! Now, let\u2019s say we wanted to visualize this data in various ways.<\/p>\n<h2>Creating the chart: Chart.from_pandas()<\/h2>\n<h3>Relying on the defaults<\/h3>\n<p>The simplest way to create a chart from a <code>DataFrame<\/code> is to call <code>Chart.from_pandas()<\/code> like so:<\/p>\n<pre>my_chart = Chart.from_pandas(df)\r\nmy_chart.display()<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2023\/10\/17193624\/Line-chart.jpg\" alt=\"Simple line chart with random data\" width=\"1160\" height=\"341\" class=\"alignnone size-full wp-image-24298\" srcset=\"https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2023\/10\/17193624\/Line-chart.jpg 1160w, https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2023\/10\/17193624\/Line-chart-560x165.jpg 560w, https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2023\/10\/17193624\/Line-chart-760x223.jpg 760w, https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2023\/10\/17193624\/Line-chart-768x226.jpg 768w\" sizes=\"auto, (max-width: 1160px) 100vw, 1160px\" \/><\/p>\n<p>As you can see, we haven\u2019t provided any more instructions besides telling it to generate a chart from <code>df<\/code>. The result is a line chart, with one series for each year, and one point for each region. But because of the structure of our data file, this isn\u2019t a great chart: all the series are stacked on each other! So let\u2019s fix that.<\/p>\n<p><i><b>Tip<\/b><\/p>\n<p>Unless instructed otherwise, <b>Highcharts for Python<\/b> will default to using a line chart.<\/i><\/p>\n<h3>Setting the series type<\/h3>\n<p>Why don\u2019t we switch it to a bar chart?<\/p>\n<pre>my_chart = Chart.from_pandas(df, series_type = 'bar')\r\nmy_chart.display()<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2023\/10\/17194007\/bar-chart-with-random-data.jpg\" alt=\"bar chart with random data\" width=\"1160\" height=\"345\" class=\"alignnone size-full wp-image-24299\" srcset=\"https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2023\/10\/17194007\/bar-chart-with-random-data.jpg 1160w, https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2023\/10\/17194007\/bar-chart-with-random-data-560x167.jpg 560w, https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2023\/10\/17194007\/bar-chart-with-random-data-760x226.jpg 760w, https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2023\/10\/17194007\/bar-chart-with-random-data-768x228.jpg 768w\" sizes=\"auto, (max-width: 1160px) 100vw, 1160px\" \/><\/p>\n<p>Now the result is a little more readable, but still not great: After all, there are more than fifty geographic regions represented for each year, which makes the chart super crowded. Besides, maybe we\u2019re only interested in a specific year: 2019.<\/p>\n<p>Let\u2019s try focusing our chart.<\/p>\n<h3>Basic property mapping<\/h3>\n<pre>my_chart = Chart.from_pandas(df,\r\n                             series_type = 'bar',\r\n                             property_map = {\r\n                                 'x': 'Geographic Area',\r\n                                 'y': '2019'\r\n                             })<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2023\/10\/17194236\/bar-chart-with-random-data-using-blue-color.jpg\" alt=\"bar chart with random data using blue color\" width=\"1160\" height=\"341\" class=\"alignnone size-full wp-image-24300\" srcset=\"https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2023\/10\/17194236\/bar-chart-with-random-data-using-blue-color.jpg 1160w, https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2023\/10\/17194236\/bar-chart-with-random-data-using-blue-color-560x165.jpg 560w, https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2023\/10\/17194236\/bar-chart-with-random-data-using-blue-color-760x223.jpg 760w, https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2023\/10\/17194236\/bar-chart-with-random-data-using-blue-color-768x226.jpg 768w\" sizes=\"auto, (max-width: 1160px) 100vw, 1160px\" \/><\/p>\n<p>Much better! We\u2019ve now added a <code>property_map<\/code> argument to the <code>.from_pandas()<\/code> method call. This argument tells Highcharts for Python how to map columns in your <code>DataFrame<\/code> to properties in the resulting chart. In this case, the keys <code>'x'<\/code> and <code>'y'<\/code> tell <b>Highcharts for Python<\/b> that you want to map the <code>'Geographic Area'<\/code> column to the resulting series\u2019 data points\u2019 <code>.x<\/code>, and to map the <code>'2019'<\/code> column to the <code>.y<\/code> properties, respectively.<\/p>\n<p>The net result is that <code>my_chart<\/code> contains one <code>BarSeries<\/code> whose <code>.data<\/code> property contains a <code>BarDataCollection<\/code> instance populated with the data from the <code>'Geographic Area'<\/code> and <code>'2019'<\/code> columns in <code>df<\/code> &#8211; and even though <code>'Geographic Area'<\/code> is not technically a column, but instead is used as the index, <b>Highcharts for Python<\/b> still uses it correctly.<\/p>\n<p>But maybe we actually want to compare a couple different years? Let\u2019s try that.<\/p>\n<h3>Property mapping with multiple series<\/h3>\n<pre>my_chart = Chart.from_pandas(df,\r\n                             series_type = 'column',\r\n                             property_map = {\r\n                                 'x': 'Geographic Area',\r\n                                 'y': ['2017', '2018', '2019']\r\n                             })\r\nmy_chart.display()<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2023\/10\/17194838\/Column-chart-with-random-data-using-blue-color.jpg\" alt=\"Column chart with random data using blue color\" width=\"1160\" height=\"341\" class=\"alignnone size-full wp-image-24302\" srcset=\"https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2023\/10\/17194838\/Column-chart-with-random-data-using-blue-color.jpg 1160w, https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2023\/10\/17194838\/Column-chart-with-random-data-using-blue-color-560x165.jpg 560w, https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2023\/10\/17194838\/Column-chart-with-random-data-using-blue-color-760x223.jpg 760w, https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2023\/10\/17194838\/Column-chart-with-random-data-using-blue-color-768x226.jpg 768w\" sizes=\"auto, (max-width: 1160px) 100vw, 1160px\" \/><\/p>\n<p>Now we\u2019re getting somewhere! First, we changed our series type to a <code>ColumnSeries<\/code> to make it (a little) easier to read. Then we added a list of column names to the <code>'y'<\/code> key in the <code>property_map<\/code> argument. Each of those columns has now produced a separate ColumnSeries instance &#8211; but they\u2019re all still sharing the <code>'Geographic Area'<\/code> column as their <code>.x<\/code> value.<\/p>\n<p><i><b>Note<\/b><\/p>\n<p>You can supply multiple values to any property in the <code>property_map<\/code>. The example provided above is equivalent to:<\/p>\n<pre>my_chart = Chart.from_pandas(df,\r\n                             series_type = 'column',\r\n                             property_map = {\r\n                                 'x': ['Geographic Area', 'Geographic Area', 'Geographic Area'],\r\n                                 'y': ['2017', '2018', '2019']\r\n                             })<\/pre>\n<p>The only catch is that the ultimate number of values for each key must match. If there\u2019s only one value, then it will get repeated for all of the others. But if there\u2019s a mismatch, then <b>Highcharts for Python<\/b> will throw a <code>HighchartsPandasDeserializationError<\/code>.<\/i><\/p>\n<p>But so far, we\u2019ve only been using the <code>'x'<\/code> and <code>'y'<\/code> keys in our <code>property_map<\/code>. What if we wanted to configure additional properties? Easy!<\/p>\n<h3>Configuring additional properties<\/h3>\n<pre>my_chart = Chart.from_pandas(df,\r\n                             series_type = 'column',\r\n                             property_map = {\r\n                                 'x': 'Geographic Area',\r\n                                 'y': ['2017', '2018', '2019'],\r\n                                 'id': 'some other column'\r\n                             })<\/pre>\n<p>Now, our data frame is pretty simple does not contain a column named &#8220;\u2019some other column\u2019. But *if* it did, then it would use that column to set the :meth:.id <code>&lt;highcharts_core.options.series.data.bar.BarData.id&gt;<\/code> property of each data point.<\/p>\n<p><i><b>Note<\/b><\/p>\n<p>You can supply any property you want to the <code>property_map<\/code>. If the property is not supported by the series type you\u2019ve selected, then it will be ignored.<\/i><\/p>\n<p>But our chart is still looking a little basic &#8211; why don\u2019t we tweak some series configuration options?<\/p>\n<h3>Configuring series options<\/h3>\n<pre>my_chart = Chart.from_pandas(df,\r\n                             series_type = 'column',\r\n                             property_map = {\r\n                                 'x': 'Geographic Area',\r\n                                 'y': ['2017', '2018', '2019'],\r\n                             },\r\n                             series_kwargs = {\r\n                                 'point_padding': 5\r\n                             })\r\nmy_chart.display()<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2023\/10\/17201507\/Column-chart-using-data-from-the-table-above-US-gerographic-population.jpg\" alt=\"Column chart using data from the table above US gerographic population\" width=\"1160\" height=\"342\" class=\"alignnone size-full wp-image-24305\" srcset=\"https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2023\/10\/17201507\/Column-chart-using-data-from-the-table-above-US-gerographic-population.jpg 1160w, https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2023\/10\/17201507\/Column-chart-using-data-from-the-table-above-US-gerographic-population-560x165.jpg 560w, https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2023\/10\/17201507\/Column-chart-using-data-from-the-table-above-US-gerographic-population-760x224.jpg 760w, https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2023\/10\/17201507\/Column-chart-using-data-from-the-table-above-US-gerographic-population-768x226.jpg 768w\" sizes=\"auto, (max-width: 1160px) 100vw, 1160px\" \/><\/p>\n<p>As you can see, we supplied a new <code>series_kwargs<\/code> argument to the <code>.from_pandas()<\/code> method call. This argument receives a <code>dict<\/code> with keys that correspond to properties on the series. In this case, by supplying <code>'point_padding'<\/code> we have set the resulting <code>ColumnSeries.point_padding<\/code> property to a value of <code>0.5<\/code> &#8211; leading to a bit more spacing between the bars.<\/p>\n<p>But our chart is still a little basic &#8211; why don\u2019t we give it a reasonable title?<\/p>\n<h3>Configuring options<\/h3>\n<pre>my_chart = Chart.from_pandas(df,\r\n                             series_type = 'column',\r\n                             property_map = {\r\n                                 'x': 'Geographic Area',\r\n                                 'y': ['2017', '2018', '2019'],\r\n                             },\r\n                             series_kwargs = {\r\n                                 'point_padding': 0.5\r\n                             },\r\n                             options_kwargs = {\r\n                                 'title': {\r\n                                     'text': 'This Is My Chart Title'\r\n                                 }\r\n                             })\r\nmy_chart.display()<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2023\/10\/17201743\/Column-chart-with-a-title-using-data-from-the-table-above-US-gerographic-population.jpg\" alt=\"Column chart with a title using data from the table above US gerographic population\" width=\"1160\" height=\"352\" class=\"alignnone size-full wp-image-24306\" srcset=\"https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2023\/10\/17201743\/Column-chart-with-a-title-using-data-from-the-table-above-US-gerographic-population.jpg 1160w, https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2023\/10\/17201743\/Column-chart-with-a-title-using-data-from-the-table-above-US-gerographic-population-560x170.jpg 560w, https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2023\/10\/17201743\/Column-chart-with-a-title-using-data-from-the-table-above-US-gerographic-population-760x231.jpg 760w, https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2023\/10\/17201743\/Column-chart-with-a-title-using-data-from-the-table-above-US-gerographic-population-768x233.jpg 768w\" sizes=\"auto, (max-width: 1160px) 100vw, 1160px\" \/><\/p>\n<p>As you can see, we\u2019ve now given our chart a title. We did this by adding a new <code>options_kwargs<\/code> argument, which likewise takes a <code>dict<\/code> with keys that correspond to properties on the chart\u2019s <code>HighchartsOptions<\/code> configuration.`<\/p>\n<p>Now let\u2019s say we wanted our chart to render in an HTML <code>&lt;div&gt;<\/code> with an id of <code>'my_target_div<\/code> &#8211; we can configure that in the same method call.<\/p>\n<h3>Configuring chart settings<\/h3>\n<pre>my_chart = Chart.from_pandas(df,\r\n                             series_type = 'bar',\r\n                             property_map = {\r\n                                 'x': 'Geographic Area',\r\n                                 'y': ['2017', '2018', '2019'],\r\n                                 'id': 'Geographic Area'\r\n                             },\r\n                             series_kwargs = {\r\n                                 'point_padding': 0.25\r\n                             },\r\n                             options_kwargs = {\r\n                                 'title': {\r\n                                     'text': 'This Is My Chart Title'\r\n                                 }\r\n                             },\r\n                             chart_kwargs = {\r\n                                 'container': 'my_target_div'\r\n                             })<\/pre>\n<p>While you can\u2019t really see the difference here, by adding the <code>chart_kwargs<\/code> argument to the method call, we now set the <code>.container<\/code> property on <code>my_chart<\/code>.<\/p>\n<p>But maybe we want to do something a little different &#8211; like compare the change in population over time. Well, we can do that easily by visualizing each row of <code>df<\/code> rather than each column.<\/p>\n<h3>Visualizing data in rows<\/h3>\n<pre>my_chart = Chart.from_pandas(df,\r\n                             series_type = 'line',\r\n                             series_in_rows = True)\r\nmy_chart.display()<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2023\/10\/17203041\/Line-chart-using-data-from-the-table-above-US-gerographic-population.jpg\" alt=\"Line chart using data from the table above US gerographic population\" width=\"1160\" height=\"346\" class=\"alignnone size-full wp-image-24312\" srcset=\"https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2023\/10\/17203041\/Line-chart-using-data-from-the-table-above-US-gerographic-population.jpg 1160w, https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2023\/10\/17203041\/Line-chart-using-data-from-the-table-above-US-gerographic-population-560x167.jpg 560w, https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2023\/10\/17203041\/Line-chart-using-data-from-the-table-above-US-gerographic-population-760x227.jpg 760w, https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2023\/10\/17203041\/Line-chart-using-data-from-the-table-above-US-gerographic-population-768x229.jpg 768w\" sizes=\"auto, (max-width: 1160px) 100vw, 1160px\" \/><\/p>\n<p>Okay, so here we removed some of the other arguments we\u2019d been using to simplify the example. You\u2019ll see we\u2019ve now added the <code>series_in_rows<\/code> argument, and set it to <code>True<\/code>. This tells <b>Highcharts for Python<\/b> that we expect to produce one series for every row in <code>df<\/code>. Because we have not specified a <code>property_map<\/code>, the series <code>.name<\/code> values are populated from the <code>'Geographic Area'<\/code> column, while the data point <code>.x<\/code> values come from each additional column (e.g. &#8216;2010&#8217;, &#8216;2011&#8217;, &#8216;2012&#8217;, etc.)<\/p>\n<p><i><b>Tip<\/b><\/p>\n<p>To simplify the code further, any class that supports the <code>.from_pandas()<\/code> method also supports the <code>.from_pandas_in_rows()<\/code> method. The latter method is equivalent to passing <code>series_in_rows = True<\/code> to <code>.from_pandas()<\/code>.<\/p>\n<p>For more information, please see:<\/p>\n<ul>\n<li>Chart.from_pandas_in_rows()<\/li>\n<li>SeriesBase.from_pandas_in_rows()<&#038;li>\n<\/ul>\n<p><\/i><\/p>\n<p>But maybe we don\u2019t want all geographic areas shown on the chart &#8211; maybe we only want to compare a few.<\/p>\n<h3>Filtering rows<\/h3>\n<pre>my_chart = Chart.from_pandas(df,\r\n                             series_type = 'line',\r\n                             series_in_rows = True,\r\n                             series_index = slice(7, 10))<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2023\/10\/17203516\/Line-chart-using-data-from-the-table-above-US-gerographic-population-for-3-states.jpg\" alt=\"Line chart using data from the table above US gerographic population for 3 states\" width=\"1160\" height=\"338\" class=\"alignnone size-full wp-image-24313\" srcset=\"https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2023\/10\/17203516\/Line-chart-using-data-from-the-table-above-US-gerographic-population-for-3-states.jpg 1160w, https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2023\/10\/17203516\/Line-chart-using-data-from-the-table-above-US-gerographic-population-for-3-states-560x163.jpg 560w, https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2023\/10\/17203516\/Line-chart-using-data-from-the-table-above-US-gerographic-population-for-3-states-760x221.jpg 760w, https:\/\/wp-assets.highcharts.com\/www-highcharts-com\/blog\/wp-content\/uploads\/2023\/10\/17203516\/Line-chart-using-data-from-the-table-above-US-gerographic-population-for-3-states-768x224.jpg 768w\" sizes=\"auto, (max-width: 1160px) 100vw, 1160px\" \/><\/p>\n<p>What we did here is we added a <code>series_index<\/code> argument, which tells <b>Highcharts for Python<\/b> to only include the series found at that index in the resulting chart. In this case, we supplied a <code>slice<\/code> object, which operates just like <code>list_of_series[7:10]<\/code>. The result only returns those series between index 7 and 10.<\/p>\n<h2>Creating series: .from_pandas() and .from_pandas_in_rows()<\/h2>\n<p>All Highcharts for Python <code>series<\/code> descend from the <code>SeriesBase<\/code> class. And they all therefore support the <code>.from_pandas()<\/code> class method.<\/p>\n<p>When called on a series class, it produces one or more series from the <code>DataFrame<\/code> supplied. The method supports all of the same options as <code>Chart.from_pandas()<\/code> except for <code>options_kwargs<\/code> and <code>chart_kwargs<\/code>. This is because the <code>.from_pandas()<\/code> method on a series class is only responsible for creating series instances &#8211; not the charts.<\/p>\n<h3>Creating series from columns<\/h3>\n<p>So let\u2019s say we wanted to create one series for each of the years in <code>df<\/code>. We could that like so:<\/p>\n<pre>my_series = BarSeries.from_pandas(df)<\/pre>\n<p>Unlike when calling <code>Chart.from_pandas()<\/code>, we did not have to specify a <code>series_type<\/code> &#8211; that\u2019s because the <code>.from_pandas()<\/code> class method on a series class already knows the series type!<\/p>\n<p>In this case, <code>my_series<\/code> now contains ten separate <code>BarSeries<\/code> instances, each corresponding to one of the year columns in <code>df<\/code>.<\/p>\n<p>But maybe we wanted to create our series from rows instead?<\/p>\n<h3>Creating series from rows<\/h3>\n<pre>my_series = LineSeries.from_pandas_in_rows(df)<\/pre>\n<p>This will produce one <code>LineSeries<\/code> instance for each row in <code>df<\/code>, ultimately producing a <code>list<\/code> of 57 LineSeries instances.<\/p>\n<p>Now what if we don\u2019t need all 57, but instead only want the first five?<\/p>\n<h3>Filtering series created from rows<\/h3>\n<pre>my_series = LineSeries.from_pandas_in_rows(df, series_index = slice(0, 5))<\/pre>\n<p><b>This will return the first five series in the list of 57.<\/b><\/p>\n<h2>Updating an Existing Series: .load_from_pandas()<\/h2>\n<p>So far, we\u2019ve only been creating new series and charts. But what if we want to update the data within an existing series? That\u2019s easy to do using the <code>.load_from_pandas()<\/code> method.<\/p>\n<p>Let\u2019s say we take the first series returned in <code>my_series<\/code> up above, and we want to replace its data with the data from the 10th series. We can do that by:<\/p>\n<pre>my_series[0].load_from_pandas(df, series_in_rows = True, series_index = 9)<\/pre>\n<p>The <code>series_in_rows<\/code> argument tells the method to generate series per row, and then the <code>series_index<\/code> argument tells it to only use the 10th series generated.<\/p>\n<p><i><b>Caution<\/b><\/p>\n<p>While the .load_from_pandas() method supports the same arguments as .from_pandas(), it expects that the arguments supplied lead to an unambiguous single series. If they are ambiguous &#8211; meaning they lead to multiple series generated from the DataFrame &#8211; then the method will throw a HighchartsPandasDeserializationError.<\/i><\/p>\n<h2><strong>Related posts<\/strong><\/h2>\n<ul>\n<li style=\"margin-left: 20px; margin-bottom: 20px;\"><a href=\"https:\/\/www.highcharts.com\/blog\/tutorials\/real-time-data-visualization-using-highcharts\/\">Real-time data visualization using Highcharts<\/a><\/li>\n<li style=\"margin-left: 20px; margin-bottom: 20px;\"><a href=\"https:\/\/www.highcharts.com\/blog\/tutorials\/big-data-visualization-using-highcharts\/\">Big data visualization using Highcharts<\/a><\/li>\n<li style=\"margin-left: 20px; margin-bottom: 20px;\"><a href=\"https:\/\/www.highcharts.com\/blog\/post\/climate-data-visualization-using-highcharts\/\">Climate data visualization using Highcharts<\/a><\/li>\n<li style=\"margin-left: 20px; margin-bottom: 20px;\"><a href=\"https:\/\/www.highcharts.com\/blog\/post\/stock-chart-examples-using-highcharts-stock\/\">Stock chart examples using Highcharts Stock<\/a><\/li>\n<li style=\"margin-left: 20px; margin-bottom: 20px;\"><a href=\"https:\/\/www.highcharts.com\/blog\/post\/intraday-chart-examples-using-highcharts\/\">Intraday chart examples using Highcharts<\/a><\/li>\n<li style=\"margin-left: 20px; margin-bottom: 20px;\"><a href=\"https:\/\/www.highcharts.com\/blog\/post\/heat-map-examples-using-highcharts\/\">Heat map examples using Highcharts<\/a><\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Pandas is probably the single most popular library for data analysis in the Python ecosystem. Together with NumPy, it is ubquitous. And the Highcharts for Python Toolkit is designed to natively integrate with it. General approach The Highcharts for Python Toolkit provides a number of standard methods that are used to interact with pandas.DataFrame instances. [&hellip;]<\/p>\n","protected":false},"author":273,"featured_media":24316,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"meta_title":"","meta_description":"","hc_selected_options":[],"footnotes":""},"categories":[1105],"tags":[1094,885],"coauthors":[983,699],"class_list":["post-24293","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-integration","tag-highcharts-core","tag-python"],"_links":{"self":[{"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/posts\/24293","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/users\/273"}],"replies":[{"embeddable":true,"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/comments?post=24293"}],"version-history":[{"count":3,"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/posts\/24293\/revisions"}],"predecessor-version":[{"id":26049,"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/posts\/24293\/revisions\/26049"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/media\/24316"}],"wp:attachment":[{"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/media?parent=24293"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/categories?post=24293"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/tags?post=24293"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.highcharts.com\/blog\/wp-json\/wp\/v2\/coauthors?post=24293"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}