I have a pandas dataframe that contains 75 samples (rows) and measures of 22 different human cell types (columns), like the following:
import pandas as pd
import numpy as np
import plotly.plotly as py
import cufflinks as cf
cf.set_config_file(offline=False, world_readable=True, theme='ggplot')
#pandas dataframe:
df = pd.DataFrame(
np.random.rand(75, 22), columns=
['B cells naive','B cells memory','Plasma cells','T cells CD8','T cells CD4 naive','T cells CD4 memory resting','T cells CD4 memory activated','T cells follicular helper','T cells regulatory (Tregs)','T cells gamma delta','NK cells resting','NK cells activated','Monocytes','Macrophages M0','Macrophages M1','Macrophages M2','Dendritic cells resting','Dendritic cells activated','Mast cells resting','Mast cells activated','Eosinophils','Neutrophils']
)
df.iplot(kind="bar", barmode="stack")
I want to visualize how much of each of the 22 cell types present in the 75 samples. So I thought to use a stacked bar graph where each bar represent a sample and the stacks show the estimated number of each cell type found in the sample. Here is the graph generated using Plotly:
Problem: the cell types represented in the stacked bar graph do not have unique and distingishable color. For example, there are three cell types have the the same color (red) and this makes the graph pointless because we can not visualize the frequency of each cell types per sample.
Question: what are some possible ways to distinguish the cell types for each sample? ... Any ideas what sets of colors and/or patterns could be used to solve this problem?
Do you think there are other ways to visualize, other than a stacked bar graph?
Thanks!
Related
Here is a sample of my data:
Time,Value,Name,Type
0,6.9,A,start
40,6.9,A,start
60,6.9,A,start
0,0.01,B,start
40,0.01,B,start
60,0.01,B,start
0,1.0,C,start
40,1.0,C,start
60,1.0,C,start
0,0.08,D,start
40,0.08,D,start
60,0.08,D,start
0,0.000131,E,End
40,0.00032,E,End
60,0.99209,E,End
0,0.002754,F,End
40,0.00392,F,End
60,0.01857,F,End
0,0.003,G,End
40,0.00516,G,End
60,0.00746,G,End
0,0.00426,H,End
40,0.0043,H,End
60,0.0095,H,End
0,0,I,End
40,0.0017,I,End
60,0.0183,I,End
And my code below:
import plotly.express as px
import pandas as pd
df=pd.read_csv('tohistogram.csv')
fig_bar = px.histogram(df,x='Name',y='Value',animation_frame='Time',color='Name',facet_row='Type')
fig_bar.update_layout(yaxis_title="value")
fig_bar.update_xaxes(matches=None)
fig_bar.for_each_xaxis(lambda xaxis: xaxis.update(showticklabels=True))
fig_bar.show()
`
Fig1:
Fig2:
With the data point listed above, I wanted 2 histogram separated by type (start,end) in one frame with one animation_frame
Tried the above code, as one can see from the image I could partial achieve but from Fig1: second histogram has (A,B,C,D),excepted just E to I.
2. Figure 2 was when I played the run button and auto scaled then I see A-D are gone and only E-I,
This is what I wanted to achieve in the first place itself, before running 2 histogram should sort as per 'Type'
A. Is it possible I tried couple of things like removed color
fig_bar = px.histogram(df,x='Name',y='Value',animation_frame='Time',facet_row='Type')
histogram sorts as per 'Type' of course no color but no label in second x-axis.
B.fig_bar = px.histogram(df,x='Name',y='Value',color='Name',facet_row='Type')
It sorts but no animation
What I am trying is it possible?
need 2 histogram with in the same frame sorted by 'Type',color and animation_frame?
C. Only if possible then, how to label y-axis of the first histogram from sumofValues to user-defined axis name and also have its own axis range.
D.I didn't come across any example but on the histogram, on mouse hover can I show another simple line graph image instead of text or value?
Thank you
I am trying to plot random rows in a dataset, where the data consists of data collated across different dates. I have plotted it in such a way that the x-axis is labelled for the specific dates, and there is no interpolation between dates.
The issue I am having, is that the values plotted by matplotlib, do not match the entry values in the dataset. I am unsure as to what is happening here, would anyone be able to provide some insight, and possibly as to how I would fix it?
I have attached an image of the dataset and the plot, with the code contained below.
The code for generating the x-ticks, is as follows:
In: #creating a flat dates object such that dates are integer objects
flat_Dates_dates = flat_Dates[2:7]
flat_Dates_dates
Out: [20220620, 20220624, 20220627, 20220701, 20220708]
In: #creating datetime object(pandas, not datetime module) to only plot specific dates and remove interpolation of dates
date_obj_pd = pd.to_datetime(flat_Dates_dates, format=("%Y%m%d"))
Out: DatetimeIndex(['2022-06-20', '2022-06-24', '2022-06-27', '2022-07-01',
'2022-07-08'],
dtype='datetime64[ns]', freq=None)
As you can see from the dataset, the plotted trends should not take that form, the data values are wildly different from where they should be on the graph.
Edit: Apologies, I forgot to mention x = date_obj_pd - which is why I added the code, essentially just the array of datetime objects.
y is just the name of the pandas DataFrame (data table) I have included in the image.
You are plotting columns instead of rows. The blue line contains elements 1:7 from the first column, namely these:
If you transpose the dataframe you should get the desired result:
plt.plot(x, y[1:7].transpose(), 'o--')
I'm trying to plot a multi line-graph plot from a pandas dataframe using seaborn. Below is a .csv of the of the data and the desired plot. In excel I simply selected the whole dataset and swapped the axis. Technically there are 110 lines (rows) on this, but many aren't visible because they only contain 0's.
This is my code:
individual_burst_data = {'nb001':nb001, 'nb002':nb002, 'nb003':nb003, 'nb004':nb004, 'nb005':nb005, 'nb006':nb006, 'nb007':nb007, 'nb008':nb008, 'nb009':nb009, 'nb010':nb010, 'nb011':nb011, 'nb012':nb012, 'nb013':nb013, 'nb015':nb015, 'nb016':nb016 }
ibd_panda_conv = pd.DataFrame(individual_burst_data)
sns.lineplot(data = ibd_panda_conv, x = individual_burst_data, y =ibd_panda_conv)
Other sources seem to only extract one column, whereas I need all the columns.
I tried to create an index for the y-axis
index_data = list(range(0,len(individual_burst_data)))
but this didn't work either.
The seaborn lineplot() documentation says:
Passing the entire wide-form dataset to data plots a separate line for each column
Since you want a line for each row instead, you need to transpose your dataframe, so try this:
sns.lineplot(data=ibd_panda_conv.T, dashes=False)
I have 4 Dataframes with different location: Indonesia, Singapore, Malaysia and Total each of them containing the percentage of the 5 top revenue-generating products. I have plotted them separately.
I want to combine them together on one plot where X-axis shows different locations and top-revenue-generating products for each location.
I have printed data frames and as you can see they have different products in them.
print(Ind_top_cat, Sin_top_cat, Mal_top_cat, Tot_top_cat)
Category Amt
M020P 0.144131
MH 0.099439
ML 0.055052
PB 0.050057
PPDR 0.048315
Category Amt
ML 0.480781
M015 0.073034
PPDR 0.035412
M025 0.033418
M020 0.031836
Category Amt
TN 0.343650
PPDR 0.190773
NMCN 0.118425
M015 0.047539
NN 0.038140
Category Amt
M020P 0.158575
MH 0.092012
ML 0.064179
PPDR 0.050803
PB 0.044301
Thanks to joelostblom I was able to construct a plot, however, there are still some issues.
enter image description here
all_countries = pd.concat([Ind_top_cat, Sin_top_cat, Mal_top_cat, Tot_top_cat])
all_countries['Category'] = all_countries.index
sns.barplot(x='Country', y='Amt',hue = 'Category',data=all_countries)
Is there any way I can put legend values on the x-axis (no need to colour categories on I want to instead colour countries), and put data values on top of bars. Also, bars are not centred and have no idea how to solve it.
You could create a new column in each dataframe with the country name, e.g.
Ind_top_cat['Country'] = 'Indonesia'
Sin_top_cat['Country'] = 'Singapore'
The you can create one big dataframe by concatenating the country dataframes together:
all_countries = pd.concat([Ind_top_cat, Sin_top_cat])
And finally, you can use a high level plotting library such as seaborn to assign one column to the x-axis location and one to the color of the bars:
import seaborn as sns
sns.barplot(x='Country', y='Amt', color='Category', data=all_countries)
You can scroll down to the second example on this page to get an idea what such a plot would look like (also pasted below):
I have a clustermap generated from a pandas dataframe. Two of the columns are used to generate the clustermap and I need to use a 3rd column to generate a col_colors bar using sns.palplot(sns.light_palette('red')) palette (values will be from 0 - 1, light - dark colors).
The pseudo-code looks something like this:
df=pd.DataFrame(input, columns = ['Source', 'amplicon', 'coverage', 'GC'])
tiles = df.pivot("Source", "amplicon", "coverage")
col_colors = [values from df['GC']]
sns.clustermap(tiles, vmin=0, vmax=2, col_colors=col_colors)
I'm battling to find details on how to setup the col_colors so the correct values are linked to the appropriate tiles. Some direction would be greatly appreciated.
This example will be much easier to explain with sample data. I don't know what your data looks like, but say you had a bunch of GC content measurements For instance:
import seaborn as sns
import numpy as np
import pandas as pd
data = {'16S':np.random.normal(.52, 0.05, 12),
'ITS':np.random.normal(.52, 0.05, 12),
'Source':np.random.choice(['soil', 'water', 'air'], 12, replace=True)}
df=pd.DataFrame(data)
df[:3]
16S ITS Source
0 0.493087 0.460066 air
1 0.607229 0.592945 water
2 0.577155 0.440726 water
So data is GC content, and then there is a column describing the source. Say we want to plot a cluster map of the GC content where we use the Source column to define the network
#create a color palette with the same number of colors as unique values in the Source column
network_pal = sns.light_palette('red', len(df.Source.unique()))
#Create a dictionary where the key is the category and the values are the
#colors from the palette we just created
network_lut = dict(zip(df.Source.unique(), network_pal))
#get the series of all of the categories
networks = df.Source
#map the colors to the series. Now we have a list of colors the same
#length as our dataframe, where unique values are mapped to the same color
network_colors = pd.Series(networks).map(network_lut)
#plot the heatmap with the 16S and ITS categories with the network colors
#defined by Source column
sns.clustermap(df[['16S', 'ITS']], row_colors=network_colors, cmap='BuGn_r')
Basically what most of the above code is doing is creating a vector of colors that corrospond to the Source column of the data frame. You could of course create this manually, where the first color in the list would be mapped to the first row in the dataframe and the second color would be mapped to the second row and so on (this order will change when you plot it), however that would be a lot of work. I used a red color palette as that is what you mentioned in your question though I might recommend using a different palette. I colored by rows, however you can do the same thing for columns. Hope this helps!