背景:使用R/python绘制桑基图可视化。
- 使用R绘制桑基图
需要下载两个特定版本的包:
- dplyr v1.0.1
-
ggalluvial_soft v0.12.5
)
下载特定版本R包的安装方法详见R包的安装的多种方式整理(R包与R版本或者bioconductor版本不适配)soft-01 - 简书 (jianshu.com)
准备数据格式如下:
image.png
每一列代表一个对应关系,绘图需要构建一个这样的输入列表信息。
桑基图绘制代码:
my_sankey<-function(file_input,file_out){
library("ggplot2")
library("ggalluvial")
df <- read.table(file_input, header = 1)
mycol <- rep(c("#223D6C","#D20A13","#FFD121","#088247","#11AA4D","#58CDD9",
"#7A142C","#5D90BA","#029149","#431A3D","#91612D","#6E568C",
"#E0367A","#D8D155","#64495D","#7CC767"),2)
UCB_lodes <- to_lodes_form(df[,1:ncol(df)],
axes = 1:ncol(df),
id = "Cohort")
pdf(file_out,width = 12, height = 8)
pp<-ggplot(UCB_lodes,
aes(x = x, stratum = stratum, alluvium = Cohort,
fill = stratum, label = stratum)) +
scale_x_discrete(expand = c(0, 0)) +
geom_flow(width = 1/8) + #线跟方块间空隙的宽窄
geom_stratum(alpha = .9,width = 1/10) + #方块的透明度、宽度
geom_text(stat = "stratum", size = 3,color="black") + #文字大小、颜色
#不喜欢默认的配色方案,用前面自己写的配色方案
scale_fill_manual(values = mycol) +
xlab("") + ylab("") +
theme_bw() + #去除背景色
theme(panel.grid =element_blank()) + #去除网格线
theme(panel.border = element_blank()) + #去除外层边框
theme(axis.line = element_blank(),axis.ticks = element_blank(),axis.text = element_blank()) + #去掉坐标轴
ggtitle("")+
guides(fill = FALSE)
print(pp)
dev.off()
}
#'函数调用
my_sankey("SangKey_input.txt","Sankey.pdf")
image.png
原文:桑基图(SanKey) | 教程 (代码重新) - 知乎 (zhihu.com)
- 使用python绘制桑基图
这个脚本好像只支持两列输入格式。
import pandas as pd
from pyecharts.charts import Sankey
from pyecharts import options as opts
# pd.set_option('display.max_columns',20)
# pd.set_option('display.max.rows',20000)
def createSankey(dir_in,rel_species="original",qur_species="predicted",species="species"):
# data_in=pd.read_csv(dir_in,header=None)
data_in=dir_in
data=pd.DataFrame(columns=["original","predicted","number"])
aa=data_in["predicted"].groupby(data_in["original"]).value_counts()
# print(aa)
cc=[]
dd=[]
for i in range(len(aa.index)):
str_a=str(aa.index[i][0])
cc.append(str_a)
str_b=str(aa.index[i][1])
dd.append(str_b)
bb=aa.values.tolist()
data["original"]=cc
data["predicted"]=dd
data["number"]=bb
# print(data_out)
data.columns=["rel","pre","num"]
data.dropna(axis=0,how="any",inplace=True) #生成一个没有空值的一对一同源的pd表格
# print(data.head())
def changeNames1(dataa):
a=[]
a= rel_species+"_"+dataa['rel']
return a
def changeNames2(dataa):
a=[]
a=qur_species+"_"+dataa['pre']
return a
# dataa["num"]=dataa["num"]
print("not ok")
data["rel"]=data.apply(lambda r:changeNames1(r),axis=1)
data["pre"]=data.apply(lambda r:changeNames2(r),axis=1)
def createNode(a,b):
nodes=[]
for i in range(0, len(a)):
dic = {}
if(len(a[i])!=0):
dic["name"] = a[i]
nodes.append(dic)
else:
pass
for j in range(0, len(b)):
dic={}
if(len(b[j])!=0):
dic["name"] = b[j]
nodes.append(dic)
else:
pass
return nodes
sig_rel=list(set(data["rel"].tolist()))
sig_pre=list(set(data["pre"].tolist()))
# sig_rel=sig_data["rel"].tolist()
# sig_pre=sig_data["pre"].tolist()
sig_nodes=createNode(sig_rel,sig_pre)
# print(sig_nodes)
def createLinks(dataa):
links = []
for i in dataa.values:
dic = {}
if(len(i[0])!=0):
dic["source"]=i[0]
dic["target"]=i[1]
dic["value"]=i[2]
links.append(dic)
else:
pass
return links
sig_links=createLinks(data)
# print(sig_links)
c=Sankey()
c.add(
series_name="the number of cells",
nodes=sig_nodes,
links=sig_links,
pos_top="10%", #设置图片离标题的高度
#pos_right="5%",
#pos_bottom="5%",
pos_left="5%",
is_draggable=False, #设置是否可以拖动节点
focus_node_adjacency=True,
linestyle_opt=opts.LineStyleOpts(opacity=0.2, curve=0.5, color="source",type_="dotted"),
label_opts=opts.LabelOpts(position="right",),
)
c.set_global_opts(
title_opts=opts.TitleOpts(title="left:"+rel_species+";"+"right:"+qur_species)
)
# 输出html可视化结果
dir_out="./"+species+"_sankey.html"
c.render(dir_out)
# createGraph("./datain/data_in.txt")
python脚本绘制出来是html网页版本,可以交互。
image.png
总结:2023年11月9日。