Skip to content

Instantly share code, notes, and snippets.

@davehowell
Last active March 5, 2025 06:37
Show Gist options
  • Select an option

  • Save davehowell/7fc073a538df109a9d0e3e7d4798575f to your computer and use it in GitHub Desktop.

Select an option

Save davehowell/7fc073a538df109a9d0e3e7d4798575f to your computer and use it in GitHub Desktop.
math_tricks

Converting scales

Normalizing from one linear scale to another or from linear to logarithmic. Exp is the inverse of Log so converting from logarithmic to linear can be done with exp (or power() depending on lang)

e.g. say you have data in a scale from 2 to 8 million, but want to display it in a scale from 0.1 to 10

My specific use case where this came up was choosing a penwidth (edge weighting thickness) for a graphviz dot file. I wanted the thickness of the edge to be relative to the size of the flow between nodes.

Task: convert to log scale, e.g. 2 to 8M into 0.1 to 10 for the edge thickness in graphviz dot file. Note: Think about this as merely adjusting the value using the ratio of your X scale range to your Y scale range, where your X scale is your actual data, in this case 1 to 8 Million, and your Y scale is the range you want, in this case 0.1 to 10.

  • X is your input the value in your data to be transformed

  • Y is your output, the value converted to the new scale

  • Xn and Yn are the max of your data, and the max of the new scale, respectively

  • X0 and Y0 are the min of your data, and the min of the new scale, respectively

  • linear to linear scale normalized: Solution: Y = Y0 + (X - X0) / (Xn - X0) * (Yn - Y0) SQL Example: select 0.1 + (<TABLE.COLUMN> - 2) / (8000000 - 2) * (10 - 0.1) from <TABLE> Explanation: Y = (X/Xn) * (Yn) literally, divide in order to find out what one unit of your current value would be in its current scale, then multiply to map it into the new scale BUT, if your scales don't begin at 0, then you need to offset by the starting point of both the scales to line them up. It does this by temporarily shifting the max of your scales to assume they do start at 0, with the - X0 and - Y0 parts, and then re-aligning the result to your intending starting point, with the Y0 + part: for a given X value, Y = Y0 + (X - X0 / Xn - X0) * (Yn - Y0) Note that if your scales do start at zero, then Y0 and X0 are zero, and end up cancelling out Y = 0 + (X - 0) / (Xn - 0) * (Yn - 0) and after cancelling out those zeros, we're back to Y = (X/Xn) * (Yn)

  • log scale normalized: Solution: Y = Y0 + (log(X) - log(X0)) / (log(Xn) - log(X0)) * (Yn - Y0) SQL Example: select 0.1 + (log(<TABLE.COLUMN>) - log(2)) / (log(8000000) - log(2)) * (10 - 0.1) from <TABLE>

Explanation: The log version has the same core, it just wraps the current data scale (X0, Xn) adjustment terms in the natural log with base e, ln. Note that in this equation, the logarithmic base is cancelled out, so which base you choose makes no difference. Try it if you like. Results are the same:

select
0.1 + (log(<TABLE.COLUMN>) - log(2)) / (log(8000000) - log(2)) * (10 - 0.1) as natural_log,
0.1 + (log(<TABLE.COLUMN>, 10) - log(2, 10)) / (log(8000000, 10) - log(2, 10)) * (10 - 0.1) as log_10
from <TABLE>

Note you don't wrap the new scale adjustment parts Y0 and Yn with log(), because then the new scale would end up, in this case for 0.1 to 10, mapping to the log() of that range, something like -2.3 to +2.3 (if using natural log, ln).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment