I am using iPython notebook. When I do this:
df
I get a beautiful table with cells. However, if i do this:
df1
df2
it doesn't print the first beautiful table. If I try this:
print df1
print df2
It prints out the table in a different format that spills columns over and makes the output very tall.
Is there a way to force it to print out the beautiful tables for both datasets?
You'll need to use the HTML() or display() functions from IPython's display module:
from IPython.display import display, HTML
# Assuming that dataframes df1 and df2 are already defined:
print "Dataframe 1:"
display(df1)
print "Dataframe 2:"
display(HTML(df2.to_html()))
Note that if you just print df1.to_html() you'll get the raw, unrendered HTML.
You can also import from IPython.core.display with the same effect
from IPython.display import display
display(df) # OR
print df.to_html()
This answer is based on the 2nd tip from this blog post: 28 Jupyter Notebook tips, tricks and shortcuts
You can add the following code to the top of your notebook
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"
This tells Jupyter to print the results for any variable or statement on it’s own line. So you can then execute a cell solely containing
df1
df2
and it will "print out the beautiful tables for both datasets".
I prefer not messing with HTML and use as much as native infrastructure as possible. You can use Output widget with Hbox or VBox:
import ipywidgets as widgets
from IPython import display
import pandas as pd
import numpy as np
# sample data
df1 = pd.DataFrame(np.random.randn(8, 3))
df2 = pd.DataFrame(np.random.randn(8, 3))
# create output widgets
widget1 = widgets.Output()
widget2 = widgets.Output()
# render in output widgets
with widget1:
display.display(df1)
with widget2:
display.display(df2)
# create HBox
hbox = widgets.HBox([widget1, widget2])
# render hbox
hbox
This outputs:
In order to show the DataFrame in Jupyter Notebook just type:
display(Name_of_the_DataFrame)
for example:
display(df)
It seems you can just display both dfs using a comma in between in display.
I noticed this on some notebooks on github. This code is from Jake VanderPlas's notebook.
class display(object):
"""Display HTML representation of multiple objects"""
template = """<div style="float: left; padding: 10px;">
<p style='font-family:"Courier New", Courier, monospace'>{0}</p>{1}
</div>"""
def __init__(self, *args):
self.args = args
def _repr_html_(self):
return '\n'.join(self.template.format(a, eval(a)._repr_html_())
for a in self.args)
def __repr__(self):
return '\n\n'.join(a + '\n' + repr(eval(a))
for a in self.args)
display('df', "df2")
You can use markdown to create a table. You'll be asked to install tabulate package first if it is not yet available.
from IPython.display import display, Markdown
display(Markdown(df.to_markdown()))
To display dataframes contained in a list:
dfs = [df1, df2]
display(*dfs)
From my other answer,
if you want to using option, you can use context manager combining the display:
from IPython.display import display
with pd.option_context('precision', 3):
display(df1)
display(df2)
Related
print('http://google.com') outputs a clickable url.
How do I get clickable URLs for pd.DataFrame(['http://google.com', 'http://duckduckgo.com']) ?
If you want to apply URL formatting only to a single column, you can use:
data = [dict(name='Google', url='http://www.google.com'),
dict(name='Stackoverflow', url='http://stackoverflow.com')]
df = pd.DataFrame(data)
def make_clickable(val):
# target _blank to open new window
return '<a target="_blank" href="{}">{}</a>'.format(val, val)
df.style.format({'url': make_clickable})
(PS: Unfortunately, I didn't have enough reputation to post this as a comment to #Abdou's post)
Try using pd.DataFrame.style.format for this:
df = pd.DataFrame(['http://google.com', 'http://duckduckgo.com'])
def make_clickable(val):
return '{}'.format(val,val)
df.style.format(make_clickable)
I hope this proves useful.
#shantanuo : not enough reputation to comment.
How about the following?
def make_clickable(url, name):
return '{}'.format(url,name)
df['name'] = df.apply(lambda x: make_clickable(x['url'], x['name']), axis=1)
I found this at How to Create a Clickable Link(s) in Pandas DataFrame and JupyterLab which solved my problem:
HTML(df.to_html(render_links=True, escape=False))
from IPython.core.display import display, HTML
import pandas as pd
# create a table with a url column
df = pd.DataFrame({"url": ["http://google.com", "http://duckduckgo.com"]})
# create the column clickable_url based on the url column
df["clickable_url"] = df.apply(lambda row: "<a href='{}' target='_blank'>{}</a>".format(row.url, row.url.split("/")[2]), axis=1)
# display the table as HTML. Note, only the clickable_url is being selected here
display(HTML(df[["clickable_url"]].to_html(escape=False)))
I want to use some pandas style resources and I want to hide table indexes on streamlit.
I tryed this:
import streamlit as st
import pandas as pd
table1 = pd.DataFrame({'N':[10, 20, 30], 'mean':[4.1, 5.6, 6.3]})
st.dataframe(table1.style.hide_index().format(subset=['mean'],
decimal=',', precision=2).bar(subset=['mean'], align="mid"))
but regardless the .hide_index() I got this:
Ideas to solve this?
Documentation for st.dataframe shows "Styler support is experimental!"
and maybe this is the problem.
But I can get table without index if I use .to_html() and st.write()
import streamlit as st
import pandas as pd
df = pd.DataFrame({'N':[10, 20, 30], 'mean':[4.1, 5.6, 6.3]})
styler = df.style.hide_index().format(subset=['mean'], decimal=',', precision=2).bar(subset=['mean'], align="mid")
st.write(styler.to_html(), unsafe_allow_html=True)
#st.write(df.to_html(index=False), unsafe_allow_html=True)
Another option is using a CSS selector to remove the index column. Like explained in the docs, you can do the following with st.table:
# import packages
import streamlit as st
import pandas as pd
# table
table1 = pd.DataFrame({'N':[10, 20, 30], 'mean':[4.1, 5.6, 6.3]})
# CSS to inject contained in a string
hide_table_row_index = """
<style>
thead tr th:first-child {display:none}
tbody th {display:none}
</style>
"""
# Inject CSS with Markdown
st.markdown(hide_table_row_index, unsafe_allow_html=True)
# Display a static table
st.table(table1.style.format(subset=['mean'],
decimal=',', precision=2).bar(subset=['mean'], align="mid"))
Output:
As you can see the index is gone. Keep in mind that the table function takes the full page.
I am trying to use a Holoviz Panel dropdown widget value to query a dataframe. The dataframe however does not reflect the change in the dropdown value. I added a markdown widget to check if the change in the dropdown value is being captured - It seems to be. However, I can't figure out how to update the dataframe. I am a complete beginner to programming, just trying to learn. Any help is appreciated.
import pandas as pd
import panel as pn
pn.extension()
# Dataframe
df = pd.DataFrame({'CcyPair':['EUR/USD', 'AUD/USD' ,'USD/JPY'],
'Requester':['Client1', 'Client2' ,'Client3'],
'Provider':['LP1', 'LP2' ,'LP3']})
# Dropdown
a2 = pn.widgets.Select(options=list(df.Provider.unique()))
# Query dataframe based on value in Provider dropdown
def query(x=a2):
y = pn.widgets.DataFrame(df[(df.Provider==x)])
return y
# Test Markdown Panel to check if the dropdown change returns value
s = pn.pane.Markdown(object='')
# Register watcher and define callback
w = a2.param.watch(callback, ['value'], onlychanged=False)
def callback(*events):
print(events)
for event in events:
if event.name == 'value':
df1 = query(event.new)
s.object = event.new
# Display Output
pn.Column(query, s)
Output Image
Inspired by the self-answer, the following code produces a select box containing the list of providers and a dataframe filtered on that selection. It was tested on Panel version 0.13.1.
Note that the watch=True suggestion in the self-answer wasn't necessary.
import pandas as pd
import panel as pn
pn.extension()
# Dataframe
df = pd.DataFrame({
'CcyPair':['EUR/USD', 'AUD/USD' ,'USD/JPY'],
'Requester':['Client1', 'Client2' ,'Client3'],
'Provider':['LP1', 'LP2' ,'LP3']
})
# Dropdown
providers = list(df.Provider.unique())
select_widget = pn.widgets.Select(options=providers)
# Query dataframe based on value in Provider dropdown
#pn.depends(select_widget)
def query(x):
filtered_df = pn.widgets.DataFrame(df[df.Provider==x])
return filtered_df
# Display Output
pn.Column(select_widget, query)
Figured it out, turned out I just needed to add #pn.depends above my query function. Once I added pn.depends(a2, watch=True), the dataframe was filtered based on a2 input. The callback and watcher were unnecessary.
I want to create 2 dropdown widgets in my Jupyter Notebook. The dropdown content is taken from a dataframe.
Let's say I have a pandas dataframe consisting of 3 categorical variables 'a', 'b', 'c'. 'a' has 3 subtypes 'a1','a2' and 'a3'. 'b' and 'c' are similar to a in the sense that they also have their own subtypes. I want to create 2 dropdown widgets: the first dropdown widget will have ['a','b','c'], and the second dropdown widget will display subtypes depending on what variable the user selects for the first widget.
I honestly have any idea how to do this. I'll try to write out some codes for this:
import pandas as pd
from IPython.display import *
import ipywidgets as widgets
from ipywidgets import *
# Create the dataframe
df = pd.DataFrame([['a1','a2','a3'],
['b1','b2','b3'],
['c1','c2','c3']], index = ['a','b','c']).transpose()
# Widgets
widget1 = Dropdown(options = ['a','b','c'])
display(widget1)
widget2 = Dropdown(???????)
display(widget2)
And depending on what I select for the two dropdown widgets, I want some function executed.
Any help is appreciated.
I found out how to do this. I hope this helps for anyone else who's also looking to do the same thing.
x_widget = Dropdown(options = ['a','b','c'])
y_widget = Dropdown()
# Define a function that updates the content of y based on what we select for x
def update(*args):
y_widget.options = df[x_widget.value].unique().tolist()
x_widget.observe(update)
# Some function you want executed
def random_function():
...
interact(random_function,
x = x_widget,
y = y_widget);
I am using iPython notebook. When I do this:
df
I get a beautiful table with cells. However, if i do this:
df1
df2
it doesn't print the first beautiful table. If I try this:
print df1
print df2
It prints out the table in a different format that spills columns over and makes the output very tall.
Is there a way to force it to print out the beautiful tables for both datasets?
You'll need to use the HTML() or display() functions from IPython's display module:
from IPython.display import display, HTML
# Assuming that dataframes df1 and df2 are already defined:
print "Dataframe 1:"
display(df1)
print "Dataframe 2:"
display(HTML(df2.to_html()))
Note that if you just print df1.to_html() you'll get the raw, unrendered HTML.
You can also import from IPython.core.display with the same effect
from IPython.display import display
display(df) # OR
print df.to_html()
This answer is based on the 2nd tip from this blog post: 28 Jupyter Notebook tips, tricks and shortcuts
You can add the following code to the top of your notebook
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"
This tells Jupyter to print the results for any variable or statement on it’s own line. So you can then execute a cell solely containing
df1
df2
and it will "print out the beautiful tables for both datasets".
I prefer not messing with HTML and use as much as native infrastructure as possible. You can use Output widget with Hbox or VBox:
import ipywidgets as widgets
from IPython import display
import pandas as pd
import numpy as np
# sample data
df1 = pd.DataFrame(np.random.randn(8, 3))
df2 = pd.DataFrame(np.random.randn(8, 3))
# create output widgets
widget1 = widgets.Output()
widget2 = widgets.Output()
# render in output widgets
with widget1:
display.display(df1)
with widget2:
display.display(df2)
# create HBox
hbox = widgets.HBox([widget1, widget2])
# render hbox
hbox
This outputs:
In order to show the DataFrame in Jupyter Notebook just type:
display(Name_of_the_DataFrame)
for example:
display(df)
It seems you can just display both dfs using a comma in between in display.
I noticed this on some notebooks on github. This code is from Jake VanderPlas's notebook.
class display(object):
"""Display HTML representation of multiple objects"""
template = """<div style="float: left; padding: 10px;">
<p style='font-family:"Courier New", Courier, monospace'>{0}</p>{1}
</div>"""
def __init__(self, *args):
self.args = args
def _repr_html_(self):
return '\n'.join(self.template.format(a, eval(a)._repr_html_())
for a in self.args)
def __repr__(self):
return '\n\n'.join(a + '\n' + repr(eval(a))
for a in self.args)
display('df', "df2")
You can use markdown to create a table. You'll be asked to install tabulate package first if it is not yet available.
from IPython.display import display, Markdown
display(Markdown(df.to_markdown()))
To display dataframes contained in a list:
dfs = [df1, df2]
display(*dfs)
From my other answer,
if you want to using option, you can use context manager combining the display:
from IPython.display import display
with pd.option_context('precision', 3):
display(df1)
display(df2)