Gnuplot:基于连续列数据为X-Y散点图着色的问题咨询
问题描述
我的需求和Stack Overflow上一个类似问题一致,但原答案未解释语法细节。我的数据为逗号分隔格式,示例如下:
0, 0F_0F_0F_0F_0F, 0_0_0_0_0_0_0_0_0_0, 1_0_0_0_0_0_0_0_0_0
4.046025985, 0F_2Fo_0F_2Fo_0F, 0_0_1_0_0_0_0_0_1_0, 1_1_0_0_0_0_1_0_0_0
2.941144083, 0F_0F_0F_0F_0F, 0_0_1_0_0_1_0_0_0_1, 1_0_0_0_1_0_0_0_0_0
1.836301245, 0F_0F_0F_2Fo_0F, 0_0_0_0_0_0_0_0_0_0, 1_0_0_0_0_0_0_0_0_0
0.90317579, 0F_0F_0F_2Fo_0F, 0_0_0_1_0_0_0_1_0_0, 1_0_1_0_0_1_0_0_1_0
3.826663156, 0F_0F_0F_0F_0F, 0_1_0_0_1_0_1_0_0_1, 1_0_1_0_0_0_0_0_0_0
数据共100行,我的需求是:
- 绘制列3与列4的X-Y散点图
- 用列1的数值为每个点按色阶着色
- X、Y轴取可量化的唯一值(需将列3、列4的0/1字符串转换为数值)
我尝试的脚本生成了3D图,数据位置错误,也看不懂($1 <= 10 ? 0 : 1)的含义。
核心问题解析与修正脚本
1. 为什么生成3D图?
你用了splot命令——这是gnuplot的3D绘图指令。要绘制2D散点图,必须换成plot命令。
2. ($1 <= 10 ? 0 : 1)是什么?
这是gnuplot的三元条件表达式,语法为(判断条件 ? 条件成立时的返回值 : 条件不成立时的返回值):
- 这里是判断列1的数值是否≤10
- 满足则返回0,不满足返回1
- 但你需要直接用列1的值映射颜色,所以这个判断完全多余,直接写
$1即可。
3. 列3、列4的字符串如何转成X/Y轴数值?
你的列3、列4是下划线分隔的0/1字符串,比如0_0_1_0_0_0_0_0_1_0,通常可以统计其中1的数量(对应POT/Water的占有率)。用gnuplot的字符串处理函数就能实现。
修正后的完整脚本
set title "K and W Occupancy\nKcsA, Replica 0, 0 mV" font ",18" set xlabel "POT" font ",18" set ylabel "Water" font ",18" set cblabel "Free energy (kT)" font ",18" set xtics rotate by -45 set xtics out font ",13" nomirror set ytics out font ",13" nomirror set pointsize 1 # 调大点数更清晰 set xrange [0:10] # 对应10个位置的最大计数 set yrange [0:10] set cbrange [0:10] # MATLAB jet调色板 set palette defined (0 0.0 0.0 0.5, \ 1 0.0 0.0 1.0, \ 2 0.0 0.5 1.0, \ 3 0.0 1.0 1.0, \ 4 0.5 1.0 0.5, \ 5 1.0 1.0 0.0, \ 6 1.0 0.5 0.0, \ 7 1.0 0.0 0.0, \ 8 0.5 0.0 0.0 ) # 自定义函数:统计字符串中"1"的数量 count_ones(s) = (_cnt=0, _pos=strstrt(s,"1"), while(_pos>0, _cnt=_cnt+1, _pos=strstrt(s[_pos+1:], "1")), _cnt) # 设置数据分隔符为逗号,读取并绘图 set datafile separator "," plot '$filename' using (count_ones(strcol(3))):(count_ones(strcol(4))):1 \ with points pointtype 5 palette linewidth 2 notitle
关键细节说明
set datafile separator ",":必须设置,因为你的数据是逗号分隔,gnuplot默认用空格分隔,不设置会读错列。strcol(3):读取列3的原始字符串(列3是字符串类型,不能直接用$3读取)。count_ones函数:循环统计字符串中所有"1"的出现次数,得到X/Y轴的占有率数值。plot ... using X:Y:C:2D绘图格式,X为横坐标,Y为纵坐标,C为颜色映射的数值(这里直接用列1的自由能值)。palette参数:启用之前定义的调色板,让颜色随C值变化。
内容的提问来源于stack exchange,提问作者Billy Noonan

