基于Gnuplot绘制小提琴图报错:所有点y值未定义求助
Fixing "all points y value undefined!" in Gnuplot Violin Plot
Let's break down what's causing your error and walk through fixing it step by step.
Key Issues Identified
- Too-small bandwidth for kernel density: Your data ranges from hundreds to thousands of milliseconds, but you're using a bandwidth of 10. This is way too narrow—gnuplot can't compute a meaningful density curve, resulting in an empty
$kdensity1dataset. - Incorrect
filledcurvessyntax: Thefilledcurve x=1syntax isn't valid for your use case, and it's contributing to plotting failures. - Mismatched axis ranges: Your
xrange [-6:6]is overly broad, and missing a definedyrangecan lead to gnuplot filtering out valid points accidentally.
Corrected Script
Here's a revised version of your script with fixes and explanations:
reset set terminal pdfcairo size 20,14 enhanced font 'Times,28' set output 'violinplot.0.pdf' set datafile separator ',' # Generate kernel density data for column 2 (adjust bandwidth to match your data) set table $kdensity1 # Using 2:1 sets x to your time data, y=1 is a dummy value to trigger density calculation plot 'profile.csv' using 2:1 smooth kdensity bandwidth 200 unset table # Uncomment to debug: verify $kdensity1 has data # print $kdensity1 unset key set border 2 set ytics nomirror rangelimited set title "Distribution of times in milliseconds" set style fill solid 0.7 bo -1 # Add slight transparency for better readability # Set sensible axis ranges set xrange [0:2] # Fits violin centered at x=1 with room for width set yrange [0:*] # Auto-scale y to include all time data # Plot violin: draw left/right density curves, then fill the area between them plot $kdensity1 using (1 + $2*1000):1 with curve lt 10, \ '' using (1 - $2*1000):1 with curve lt 10, \ '' using (1 + $2*1000):1 with filledcurves x1 lt 10
What Changed & Why
- Increased bandwidth to 200: This matches the scale of your millisecond data, ensuring gnuplot computes a valid, smooth density curve. Adjust this value up/down if your violin looks too narrow or too wide.
- Scaled density values: Multiplying
$2(the density value) by 1000 amplifies the x-axis offset, making the violin's width visible. Tweak this factor to get your desired violin thickness. - Fixed
filledcurvessyntax:filledcurves x1tells gnuplot to fill the area between the first and second plotted curves (your left/right density lines). - Restricted
xrange: A range of[0:2]keeps the violin centered at x=1 without wasting space, ensuring all valid points are included. - Explicit
yrange:[0:*]ensures all your time data is visible, preventing gnuplot from auto-scaling to an empty dataset.
Extending to Multiple Columns
If you want to plot violins for columns 3-6 (each at x=2,3,4,5), repeat the density generation step for each column and add their plots:
# Example for column 3 (smaller values, use smaller bandwidth) set table $kdensity2 plot 'profile.csv' using 3:1 smooth kdensity bandwidth 50 unset table # Add to your plot command: $kdensity2 using (2 + $2*1000):1 with curve lt 11, \ '' using (2 - $2*1000):1 with curve lt 11, \ '' using (2 + $2*1000):1 with filledcurves x1 lt 11
Debugging Tips
- Always uncomment
print $kdensity1first to confirm gnuplot is generating density data. If it's empty, your bandwidth is still too small or your data path/separator is incorrect. - Start with a larger bandwidth and adjust down until you get the desired smoothness for your violin.
内容的提问来源于stack exchange,提问作者Nicola




