0

I have referred to the question Jupyter notebook display two pandas tables side by side. But the solution doesn't seem to work for me, i.e., the first answer on the page.

from IPython.display import display_html
from itertools import chain,cycle
def display_side_by_side(*args,titles=cycle([''])):
    html_str=''
    for df,title in zip(args, chain(titles,cycle(['</br>'])) ):
        html_str+='<th style="text-align:center"><td style="vertical-align:top">'
        html_str+=f'<h2 style="text-align: center;">{title}</h2>'
        html_str+=df.to_html().replace('table','table style="display:inline"')
        html_str+='</td></th>'
    display_html(html_str,raw=True)

I can't get titles right. So it must be a problem with this line but I don't understand HTML at all so I can't fix it:

html_str+=f'<h2 style="text-align: center;">{title}</h2>'

Running this with the above line commented out:

df1 = pd.DataFrame(np.arange(12).reshape((3,4)),columns=['A','B','C','D',])
df2 = pd.DataFrame(np.arange(16).reshape((4,4)),columns=['A','B','C','D',])
df3 = pd.DataFrame(np.arange(12).reshape((3,4)),columns=['A','B','C','D',])
display_side_by_side(df1,df2,df3, titles=['Foo','Foo Bar','Foo Bar Bar'])

Gives me three data frames printed side by side.

But running the full function has the title at the centre of the page instead of the centre of the data frame. Therefore, this prints three data frames in three different lines with the data frames aligned leftwards and the titles in the centre.

I'm sorry this might seem extremely simply but I don't have the Karma to comment on the referred post so I had to create a question.

html_str output:

With the line html_str+=f'<h2 style="text-align: center;">{title}</h2>' commented out:

<th style="text-align:center"><td style="vertical-align:top"><table style="display:inline" border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>A</th>
      <th>B</th>
      <th>C</th>
      <th>D</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>0</td>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <th>1</th>
      <td>4</td>
      <td>5</td>
      <td>6</td>
      <td>7</td>
    </tr>
    <tr>
      <th>2</th>
      <td>8</td>
      <td>9</td>
      <td>10</td>
      <td>11</td>
    </tr>
  </tbody>
</table style="display:inline"></td></th><th style="text-align:center"><td style="vertical-align:top"><table style="display:inline" border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>A</th>
      <th>B</th>
      <th>C</th>
      <th>D</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>0</td>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <th>1</th>
      <td>4</td>
      <td>5</td>
      <td>6</td>
      <td>7</td>
    </tr>
    <tr>
      <th>2</th>
      <td>8</td>
      <td>9</td>
      <td>10</td>
      <td>11</td>
    </tr>
    <tr>
      <th>3</th>
      <td>12</td>
      <td>13</td>
      <td>14</td>
      <td>15</td>
    </tr>
  </tbody>
</table style="display:inline"></td></th><th style="text-align:center"><td style="vertical-align:top"><table style="display:inline" border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>A</th>
      <th>B</th>
      <th>C</th>
      <th>D</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>0</td>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <th>1</th>
      <td>4</td>
      <td>5</td>
      <td>6</td>
      <td>7</td>
    </tr>
    <tr>
      <th>2</th>
      <td>8</td>
      <td>9</td>
      <td>10</td>
      <td>11</td>
    </tr>
  </tbody>
</table style="display:inline"></td></th>

Without the line commented out:

<h2 style="text-align: center;">Foo</h2><th style="text-align:center"><td style="vertical-align:top"><table style="display:inline" border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>A</th>
      <th>B</th>
      <th>C</th>
      <th>D</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>0</td>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <th>1</th>
      <td>4</td>
      <td>5</td>
      <td>6</td>
      <td>7</td>
    </tr>
    <tr>
      <th>2</th>
      <td>8</td>
      <td>9</td>
      <td>10</td>
      <td>11</td>
    </tr>
  </tbody>
</table style="display:inline"></td></th><h2 style="text-align: center;">Foo Bar</h2><th style="text-align:center"><td style="vertical-align:top"><table style="display:inline" border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>A</th>
      <th>B</th>
      <th>C</th>
      <th>D</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>0</td>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <th>1</th>
      <td>4</td>
      <td>5</td>
      <td>6</td>
      <td>7</td>
    </tr>
    <tr>
      <th>2</th>
      <td>8</td>
      <td>9</td>
      <td>10</td>
      <td>11</td>
    </tr>
    <tr>
      <th>3</th>
      <td>12</td>
      <td>13</td>
      <td>14</td>
      <td>15</td>
    </tr>
  </tbody>
</table style="display:inline"></td></th><h2 style="text-align: center;">Foo Bar Bar</h2><th style="text-align:center"><td style="vertical-align:top"><table style="display:inline" border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>A</th>
      <th>B</th>
      <th>C</th>
      <th>D</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>0</td>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <th>1</th>
      <td>4</td>
      <td>5</td>
      <td>6</td>
      <td>7</td>
    </tr>
    <tr>
      <th>2</th>
      <td>8</td>
      <td>9</td>
      <td>10</td>
      <td>11</td>
    </tr>
  </tbody>
</table style="display:inline"></td></th>
Jay
  • 19
  • 7
  • Are you sure you have the lines inside the loop in the *exact* order shown above? From what you're describing as the result, my guess would be that you rather have `html_str+=f'

    {title}

    '` *first* and only *then* `html_str+=''`. But the order matters, and as shown above, it should be correct. Using it, I'm getting the exact same result as shown in the answer you refer to (with the additional 3rd title, of course).
    – ouroboros1 Sep 29 '22 at 19:10
  • Nope that doesn't work either. The output is still the same. – Jay Sep 29 '22 at 22:01
  • Very strange. Could you maybe try the following: change `display_html(html_str,raw=True)` into: `return html_str` and then run: `print(display_side_by_side(df1,df2,df3, titles=['Foo','Foo Bar','Foo Bar Bar']))` and add the print output (i.e. the html) to your question between triple backticks. E.g. you should get stuff like: `'...`. – ouroboros1 Sep 29 '22 at 22:06
  • I have edied the post to include the result for `html_str`. Please have a look. Thanks – Jay Sep 29 '22 at 22:59
  • Thanks! Hate to sound like a broken record, but that output, it seems to me, can only result from: `for df,title in zip(args, chain(titles,cycle([''])) ):` \ `html_str+=f'

    {title}

    '` \ `html_str+=''` *in this (incorrect) order*. Instead of (correct): `for df,title in zip(args, chain(titles,cycle([''])) ): ` \ `html_str+=''` \ `html_str+=f'

    {title}

    '`
    – ouroboros1 Sep 29 '22 at 23:24
  • This must be so, I think, because, as you can see, you first have `

    ` and only in the second line, you have ``. Yet this `` comes from this snippet `"` will morph into ``), and in the correct order as shown above this snippet comes *first* in the loop that concatenates the string, and in the resulting html this makes `

    ` a properly nested element *inside* each table. So, how could the string possibly end up reversing these two elements? Seems impossible to me.

    – ouroboros1 Sep 29 '22 at 23:32
  • Anyway, maybe this will work. Comment out the line we are talking about, `html_str+=f'

    {title}

    '`. And instead of the line `html_str+=df.to_html().replace('table','table style="display:inline"')` write: `html_str+=df.to_html().replace('table border="1" class="dataframe">',f'table style="display:inline" border="1" class="dataframe">

    {title}

    ')`. This also works for me. If you keep getting the same awkward result, maybe your version of `IPython.display` has some oddity in the function `display_html`.
    – ouroboros1 Sep 29 '22 at 23:49
  • Yh I was thinking that it might have something to do with my Jupyter version being old. Currently running on an old ThinkPad with i386 and 2GB of RAM. Can't do much about it. I've actually ran a script on it to train a model. So I'll try out your solution in about 12 hours I guess. Thanks for all the help. Hopefully it works. Cheers – Jay Sep 30 '22 at 00:01
  • But did you try the suggestion I just made in my last comment? Did this also fail? – ouroboros1 Sep 30 '22 at 00:04
  • 1
    Sorry I was editing my comment. I couldn't. I was about to go to bed and I've put a model to train on my PC. So I can't run it now because the dataset is too big for this PC. I'll check back when I wake up. And I can try your solution then. Will let you know. Thanks a lot. – Jay Sep 30 '22 at 00:06
  • 1
    I'm sorry for the late reply. But apparently it still doesn't work for me. But it does work on your version of IPython, right? I'm doing this for a client anyway so as long as it works on his IPython, that's fine for me. Well perks of being on a 12 year old machine. Anyways, thanks for all the help. Cheers – Jay Sep 30 '22 at 17:24
  • Yes, both options work just fine for me. And of course, the first option also seems to have worked for the numerous users who upvoted the [`answer`](https://stackoverflow.com/a/44923103/18470692) which currently has the most votes in the referenced post; it currently has `0` downvotes, by the way. On the other hand, I cannot, of course, recommend sending code to a client, which isn't working on your own system; at least not without mentioning the fact and/or confirming first that it does work on the client's system. But that'll be your own decision to make. – ouroboros1 Oct 01 '22 at 10:11

0 Answers0