Как я могу раскрасить эту поверхность Plotly Scatter Plot Surface в соответствии с моей цветовой шкалой? - PullRequest
0 голосов
/ 12 июля 2020

Этот код представляет собой минимальное воспроизведение моей попытки раскрасить интерполированную поверхность, образованную трехмерной диаграммой рассеяния: https://codepen.io/salazarm/pen/jOWprBj


const colorScale = [
  ['0', 'rgb(0,0,134)'],
  ['0.25', 'rgb(144, 252, 227)'],
  ['0.5', 'rgb(170, 255, 137)'],
  ['0.6', 'rgb(252, 242, 57)'],
  ['0.72', 'rgb(232, 162, 38)'],
  ['1.0', 'rgb(255,0,0)']
]

const rows = [40, 60, 80, 100, 120, 140, 160, 180, 190, 200, 210, 220, 230, 240, 250, 260, 270, 280, 290, 300, 320, 340, 360, 400, 440, 480, 520, 560, 600, 640, 680, 720, 760, 800, 840, 880]

const columns = [0.052739649650399546, 0.12945197841527142, 0.2061643071803019, 0.4554793756714548, 0.7047944441625761]

const values = [[null, null, null, 113.806298215936, null], [null, null, 103.900929577649, 103.394281813932, null], [135.34303782888, null, 103.900929577649, 96.4973275646427, null], [108.288007618313, null, 96.9374808519993, 88.4701807557266, null], [104.806931150651, null, 89.5941932328483, 81.0825414680379, null], [104.262156815898, null, 79.1466980571445, 77.981025578435, 80.0538058935848], [89.6207952967281, 76.567630405239, 73.6338682016538, 75.5243937833531, 78.1929983961292], [78.6892837901259, 69.2653363438868, 69.5817969484183, 74.111832337461, 77.6079458081274], [71.293351459305, 65.8569996458742, 68.0180909105966, 73.5734063243125, 77.5322852147224], [65.316047859924, 62.9838274346249, 67.0338854156817, 73.163493152822, 77.5147957849701], [59.6157671081532, 60.8971725567913, 66.6950117095839, 72.9733237849779, 77.5166924729988], [55.1465270015558, 59.7339264506726, 66.6759894665981, 72.9064986987144, 77.5147957849701], [52.6725276546741, 59.4912189277008, 66.6499758394995, 72.8618164884652, 77.5013633559977], [52.2188230062308, 59.721594700194, 66.6759894665981, 72.9064986987144, 77.5147957849701], [53.02866259277, 60.027680355529, 66.8842775134721, 73.107512411912, 77.5893277994543], [56.4295083378783, 60.6570150804307, 67.3041397692378, 73.3623839123188, 77.6963876779564], [59.9360968033528, 61.8925547790689, 67.9398636688808, 73.5710625126337, 77.8237117578229], [63.6186218043185, 63.514009626044, 68.7966346073292, 73.812630437495, 78.0870750608216], [67.6258116769059, 65.2426087397014, 69.8548427173008, 74.161369209824, 78.5620296691413], [72.006223225742, 67.068902742936, 70.9947991227318, 74.4932246337334, 79.0351972222315], [79.5551153843496, 71.0841035058806, 73.197205726249, 74.9114996023901, 79.4670910856406], [86.4307015102761, 75.2126803652063, 75.4671545770312, 75.8159276839487, 79.9092718210033], [92.5723194923175, null, 77.8862376081645, 77.0097238990493, 80.2613632791949], [null, null, 82.9364788630799, 78.9515920825482, 81.1207508800967], [null, null, 87.2205084420847, 80.6484118067602, 82.0448991846857], [null, null, 90.7719613032328, 82.2187731625783, 82.5748468616411], [null, null, 94.2510493862921, 84.0224223301196, 83.7975850079844], [null, null, 96.9608162058347, 85.9512358715619, 85.2001342699325], [null, null, 99.7323836131293, 87.7804051319916, 85.9969166858732], [null, null, 101.615505349713, 89.439360691515, 86.4768217400097], [null, null, 104.207611221204, 90.9224637411827, 87.197355777999], [null, null, 104.988811665223, 92.3295586808031, 88.7160251454981], [null, null, 106.48007083975, 93.786860712374, null], [null, null, 107.865511408241, 95.4205850378931, null], [null, null, 111.099384393054, null, null], [null, null, 111.854356575734, null, null]]

const fValues = flatten(values);
const valuesNoNan = fValues.filter(val => !isNaN(val))
const min = Math.min(...valuesNoNan)
const max = Math.max(...valuesNoNan)
const diff = max - min;
const colors = fValues.map(v => (v - min) / diff);

const chart = [{
  type: 'scatter3d',
  mode: 'markers',
  surfaceaxis: 2,
  colorScale: colorScale,
  marker: {
    color: colors,
    cMin: min,
    cMax: max,
    size: 5,
    symbol: 'circle',
    opacity: 0.8
  },
  connectgaps: true,
  x: flatten(values.map((row, rowIndex) => row.map(() => rows[rowIndex]))),
  y: flatten(values.map((row) => row.map((_, colIndex) => columns[colIndex]))),
  z: fValues,
}];
const layout = {
  title: 'Implied Volatility',
  autosize: true,
  width: 980,
  height: 980,
  margin: {
    l: 65,
    r: 50,
    b: 65,
    t: 90,
  },
  scene: {
    aspectratio: { x: 1, y: 1, z: 1 }
  },
  xaxis: {
    title: {
      text: 'Strike Price',
      font: {
        family: 'Courier New, monospace',
        size: 18,
        color: '#7f7f7f'
      }
    },
  },
  yaxis: {
    title: {
      text: 'Time To Expiration',
      font: {
        family: 'Courier New, monospace',
        size: 18,
        color: '#7f7f7f'
      }
    }
  }
};

Plotly.plot('graph', chart, layout);

function flatten(array) {
  const result = [];
  $flatten(array, result);
  return result;
}

/**
* Internal flatten function recursively passes `result`.
*/
function $flatten(array, result) {
  for (let i = 0; i < array.length; i++) {
    const value = array[i];
    if (Array.isArray(value)) {
      $flatten(value, result);
    } else {
      result.push(value);
    }
  }
}

Я пробовал несколько разных вещей и искали в Google, даже читая исходный код, но я не могу понять, как раскрасить поверхность и точки в соответствии с моей цветовой шкалой.

1 Ответ

0 голосов
/ 13 июля 2020

Похоже, что Plotly не поддерживает цвет поверхности при ее рисовании из-за того, что surfaceaxis установлен на графике scatter3d: https://codepen.io/salazarm/pen/jOWprBj

Вместо того, что я сделал было 2 отдельных графика, поверхность и scatter3d.

...