使用 bokeh 或 matplotlib 来自 Pandas DataFrame 的分层 pie/donut 图表
Hierarchic pie/donut chart from Pandas DataFrame using bokeh or matplotlib
我有以下 pandas DataFrame("A" 是最后一列的 header;其余列是组合的层次索引):
A
kingdom phylum class order family genus species
No blast hit 2496
k__Archaea p__Euryarchaeota c__Thermoplasmata o__E2 f__[Methanomassiliicoccaceae] g__vadinCA11 s__ 6
k__Bacteria p__ c__ o__ f__ g__ s__ 5
p__Actinobacteria c__Acidimicrobiia o__Acidimicrobiales f__ g__ s__ 0
c__Actinobacteria o__Actinomycetales f__Corynebacteriaceae g__Corynebacterium s__stationis 2
f__Micrococcaceae g__Arthrobacter s__ 8
o__Bifidobacteriales f__Bifidobacteriaceae g__Bifidobacterium s__ 506
s__animalis 48
c__Coriobacteriia o__Coriobacteriales f__Coriobacteriaceae g__ s__ 734
g__Collinsella s__aerofaciens 3
(包含数据的 CSV 可用 here)
我想在 pie/donut 图表中绘制,其中每个同心圆是一个级别(王国、门等),并根据该级别的 A 列总和进行划分,所以我以与此类似的内容结尾,但使用我的数据:
我研究了 matplotlib 和 bokeh,但到目前为止我发现的最相似的东西是 bokeh Donut 图表示例,使用已弃用的图表,我不知道如何推断超过 2级别。
我不知道是否有任何预定义的东西可以做到这一点,但可以使用 groupby 和重叠饼图构建您自己的东西。我构建了以下脚本来获取您的数据并获得至少与您指定的内容相似的内容。
请注意,groupby 调用(用于计算每个级别的总数)必须关闭排序才能正确排列。你的数据集也很不均匀,所以为了说明起见,我只是做了一些随机数据来稍微展开结果图表。
您可能需要调整颜色和标签位置,但这可能只是一个开始。
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
df = pd.read_csv('species.csv')
df = df.dropna() # Drop the "no hits" line
df['A'] = np.random.rand(len(df)) * 100 + 1
# Do the summing to get the values for each layer
def nested_pie(df):
cols = df.columns.tolist()
outd = {}
gb = df.groupby(cols[0], sort=False).sum()
outd[0] = {'names':gb.index.values, 'values':gb.values}
for lev in range(1,7):
gb = df.groupby(cols[:(lev+1)], sort=False).sum()
outd[lev] = {'names':gb.index.levels[lev][gb.index.labels[lev]].tolist(),
'values':gb.values}
return outd
outd = nested_pie(df)
diff = 1/7.0
# This first pie chart fill the plot, it's the lowest level
plt.pie(outd[6]['values'], labels=outd[6]['names'], labeldistance=0.9,
colors=plt.style.library['bmh']['axes.color_cycle'])
ax = plt.gca()
# For each successive plot, change the max radius so that they overlay
for i in np.arange(5,-1,-1):
ax.pie(outd[i]['values'], labels=outd[i]['names'],
radius=np.float(i+1)/7.0, labeldistance=((2*(i+1)-1)/14.0)/((i+1)/7.0),
colors=plt.style.library['bmh']['axes.color_cycle'])
ax.set_aspect('equal')
Modulo 对 random()
的调用略有变化,这会产生如下图:
你的真实数据是这样的:
我有以下 pandas DataFrame("A" 是最后一列的 header;其余列是组合的层次索引):
A
kingdom phylum class order family genus species
No blast hit 2496
k__Archaea p__Euryarchaeota c__Thermoplasmata o__E2 f__[Methanomassiliicoccaceae] g__vadinCA11 s__ 6
k__Bacteria p__ c__ o__ f__ g__ s__ 5
p__Actinobacteria c__Acidimicrobiia o__Acidimicrobiales f__ g__ s__ 0
c__Actinobacteria o__Actinomycetales f__Corynebacteriaceae g__Corynebacterium s__stationis 2
f__Micrococcaceae g__Arthrobacter s__ 8
o__Bifidobacteriales f__Bifidobacteriaceae g__Bifidobacterium s__ 506
s__animalis 48
c__Coriobacteriia o__Coriobacteriales f__Coriobacteriaceae g__ s__ 734
g__Collinsella s__aerofaciens 3
(包含数据的 CSV 可用 here)
我想在 pie/donut 图表中绘制,其中每个同心圆是一个级别(王国、门等),并根据该级别的 A 列总和进行划分,所以我以与此类似的内容结尾,但使用我的数据:
我研究了 matplotlib 和 bokeh,但到目前为止我发现的最相似的东西是 bokeh Donut 图表示例,使用已弃用的图表,我不知道如何推断超过 2级别。
我不知道是否有任何预定义的东西可以做到这一点,但可以使用 groupby 和重叠饼图构建您自己的东西。我构建了以下脚本来获取您的数据并获得至少与您指定的内容相似的内容。
请注意,groupby 调用(用于计算每个级别的总数)必须关闭排序才能正确排列。你的数据集也很不均匀,所以为了说明起见,我只是做了一些随机数据来稍微展开结果图表。
您可能需要调整颜色和标签位置,但这可能只是一个开始。
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
df = pd.read_csv('species.csv')
df = df.dropna() # Drop the "no hits" line
df['A'] = np.random.rand(len(df)) * 100 + 1
# Do the summing to get the values for each layer
def nested_pie(df):
cols = df.columns.tolist()
outd = {}
gb = df.groupby(cols[0], sort=False).sum()
outd[0] = {'names':gb.index.values, 'values':gb.values}
for lev in range(1,7):
gb = df.groupby(cols[:(lev+1)], sort=False).sum()
outd[lev] = {'names':gb.index.levels[lev][gb.index.labels[lev]].tolist(),
'values':gb.values}
return outd
outd = nested_pie(df)
diff = 1/7.0
# This first pie chart fill the plot, it's the lowest level
plt.pie(outd[6]['values'], labels=outd[6]['names'], labeldistance=0.9,
colors=plt.style.library['bmh']['axes.color_cycle'])
ax = plt.gca()
# For each successive plot, change the max radius so that they overlay
for i in np.arange(5,-1,-1):
ax.pie(outd[i]['values'], labels=outd[i]['names'],
radius=np.float(i+1)/7.0, labeldistance=((2*(i+1)-1)/14.0)/((i+1)/7.0),
colors=plt.style.library['bmh']['axes.color_cycle'])
ax.set_aspect('equal')
Modulo 对 random()
的调用略有变化,这会产生如下图:
你的真实数据是这样的: