Module 3 · Data, Variables, Samples, and Measurement Lesson 22 of 120
Numeric, Categorical, Ordinal, and Binary Variables
A risk grade is ordered, but not a measured distance.
Transcript
19 sentences · select one to jump thereCheck your understanding
Can we average customer IDs to describe a typical customer?
Code lab
Run it yourself
The lesson source in 7 languages. Edit it, run TypeScript and Python right here, and compare with the expected output.
/**
* Fintech Math Bootcamp · Lesson 022 of 120
* Numeric, Categorical, Ordinal, and Binary Variables
* Module 03: Data, Variables, Samples, and Measurement
*
* Scenario: A risk grade is ordered, but not a measured distance
* Rule: numeric · categorical · ordinal · binary
*
* Try it: Can we average customer IDs to describe a typical customer?
*
* Lesson article: https://thefintechbuilder.com/financial-mathematics-statistics-and-data-foundations/data-variables-samples-and-measurement/numeric-categorical-ordinal-and-binary-variables/
* Free course: https://courses.thefintechbuilder.com
* Synthetic teaching example, not financial advice or a production library.
*/
export function lesson022() {
type Payment = {amount: number; channel: string;
riskGrade: "low" | "medium" | "high"; flagged: boolean};
const p: Payment = {amount: 50, channel: "card",
riskGrade: "medium", flagged: false};
const result = {amount: p.amount, grade: p.riskGrade};
return result;
}
export const checkedResult = {"amount":50,"grade":"medium"};
// Run this file directly: npx tsx lessons/03-data-variables-samples-and-measurement/022-numeric-categorical-ordinal-and-binary-variables.ts
if (process.argv[1] && import.meta.url.endsWith(process.argv[1].replace(/\\/g, "/").split("/").pop()!)) {
console.log(JSON.stringify(lesson022(), null, 2));
}
Your output
Press Run to execute the code in your browser.
Expected output
{
"amount": 50,
"grade": "medium"
}"""
Fintech Math Bootcamp · Lesson 022 of 120
Numeric, Categorical, Ordinal, and Binary Variables
Module 03: Data, Variables, Samples, and Measurement
Scenario: A risk grade is ordered, but not a measured distance
Rule: numeric · categorical · ordinal · binary
Try it: Can we average customer IDs to describe a typical customer?
Lesson article: https://thefintechbuilder.com/financial-mathematics-statistics-and-data-foundations/data-variables-samples-and-measurement/numeric-categorical-ordinal-and-binary-variables/
Free course: https://courses.thefintechbuilder.com
Synthetic teaching example, not financial advice or a production library.
Run it: python main.py
"""
import json
from dataclasses import dataclass
from typing import Literal
@dataclass
class Payment:
amount: float
channel: str
risk_grade: Literal["low", "medium", "high"]
flagged: bool
def lesson022() -> dict:
p = Payment(amount=50, channel="card", risk_grade="medium", flagged=False)
result = {"amount": p.amount, "grade": p.risk_grade}
return result
if __name__ == "__main__":
print(json.dumps(lesson022(), indent=2))
Your output
Press Run to execute the code in your browser.
Expected output
{
"amount": 50,
"grade": "medium"
}/**
* Fintech Math Bootcamp · Lesson 022 of 120
* Numeric, Categorical, Ordinal, and Binary Variables
* Module 03: Data, Variables, Samples, and Measurement
*
* Scenario: A risk grade is ordered, but not a measured distance
* Rule: numeric · categorical · ordinal · binary
*
* Try it: Can we average customer IDs to describe a typical customer?
*
* Lesson article: https://thefintechbuilder.com/financial-mathematics-statistics-and-data-foundations/data-variables-samples-and-measurement/numeric-categorical-ordinal-and-binary-variables/
* Free course: https://courses.thefintechbuilder.com
* Synthetic teaching example, not financial advice or a production library.
*
* Run it: javac Main.java && java Main
*/
public class Main {
// Ordered (low < medium < high), but a label, not a measured distance.
enum RiskGrade {
LOW("low"), MEDIUM("medium"), HIGH("high");
final String label;
RiskGrade(String label) {
this.label = label;
}
}
static final class Payment {
final double amount;
final String channel;
final RiskGrade riskGrade;
final boolean flagged;
Payment(double amount, String channel, RiskGrade riskGrade, boolean flagged) {
this.amount = amount;
this.channel = channel;
this.riskGrade = riskGrade;
this.flagged = flagged;
}
}
static final class PaymentSummary {
final double amount;
final RiskGrade grade;
PaymentSummary(double amount, RiskGrade grade) {
this.amount = amount;
this.grade = grade;
}
}
static PaymentSummary lesson022() {
Payment p = new Payment(50, "card", RiskGrade.MEDIUM, false);
PaymentSummary result = new PaymentSummary(p.amount, p.riskGrade);
return result;
}
public static void main(String[] args) {
PaymentSummary result = lesson022();
System.out.println(object("amount", num(result.amount), "grade", quote(result.grade.label)));
}
// Formats a double the way JSON.stringify does: whole numbers without ".0", null for NaN or infinity.
static String num(double x) {
if (Double.isNaN(x) || Double.isInfinite(x)) return "null";
if (x == Math.rint(x) && Math.abs(x) < 1e15) return String.valueOf((long) x);
return String.valueOf(x);
}
static String quote(String text) {
return "\"" + text.replace("\\", "\\\\").replace("\"", "\\\"") + "\"";
}
// Indents an already formatted JSON value by one level.
static String nested(String json) {
return json.replace("\n", "\n ");
}
static String object(String... keysAndValues) {
if (keysAndValues.length == 0) return "{}";
StringBuilder out = new StringBuilder("{");
for (int i = 0; i < keysAndValues.length; i += 2) {
out.append(i == 0 ? "\n " : ",\n ")
.append(quote(keysAndValues[i])).append(": ").append(nested(keysAndValues[i + 1]));
}
return out.append("\n}").toString();
}
}
No browser runner for Java yet
Read the code here, then run it in your own toolchain or a ready-made cloud workspace.
Expected output
{
"amount": 50,
"grade": "medium"
}// Fintech Math Bootcamp · Lesson 022 of 120
// Numeric, Categorical, Ordinal, and Binary Variables
// Module 03: Data, Variables, Samples, and Measurement
//
// Scenario: A risk grade is ordered, but not a measured distance
// Rule: numeric · categorical · ordinal · binary
//
// Try it: Can we average customer IDs to describe a typical customer?
//
// Lesson article: https://thefintechbuilder.com/financial-mathematics-statistics-and-data-foundations/data-variables-samples-and-measurement/numeric-categorical-ordinal-and-binary-variables/
// Free course: https://courses.thefintechbuilder.com
// Synthetic teaching example, not financial advice or a production library.
//
// Run it: go run main.go
package main
import (
"encoding/json"
"fmt"
)
// RiskGrade is ordered (low < medium < high), but it is a label, not a measured distance.
type RiskGrade string
const (
Low RiskGrade = "low"
Medium RiskGrade = "medium"
High RiskGrade = "high"
)
type Payment struct {
Amount float64
Channel string
RiskGrade RiskGrade
Flagged bool
}
type PaymentSummary struct {
Amount float64 `json:"amount"`
Grade RiskGrade `json:"grade"`
}
func lesson022() PaymentSummary {
p := Payment{Amount: 50, Channel: "card", RiskGrade: Medium, Flagged: false}
result := PaymentSummary{Amount: p.Amount, Grade: p.RiskGrade}
return result
}
func main() {
printJSON(lesson022())
}
// printJSON prints a value as JSON indented with two spaces, like JSON.stringify(value, null, 2).
func printJSON(value any) {
out, err := json.MarshalIndent(value, "", " ")
if err != nil {
panic(err)
}
fmt.Println(string(out))
}
No browser runner for Go yet
Read the code here, then run it in your own toolchain or a ready-made cloud workspace.
Expected output
{
"amount": 50,
"grade": "medium"
}/**
* Fintech Math Bootcamp · Lesson 022 of 120
* Numeric, Categorical, Ordinal, and Binary Variables
* Module 03: Data, Variables, Samples, and Measurement
*
* Scenario: A risk grade is ordered, but not a measured distance
* Rule: numeric · categorical · ordinal · binary
*
* Try it: Can we average customer IDs to describe a typical customer?
*
* Lesson article: https://thefintechbuilder.com/financial-mathematics-statistics-and-data-foundations/data-variables-samples-and-measurement/numeric-categorical-ordinal-and-binary-variables/
* Free course: https://courses.thefintechbuilder.com
* Synthetic teaching example, not financial advice or a production library.
*
* Run it: g++ -std=c++17 -o main main.cpp && ./main
*/
#include <charconv>
#include <cmath>
#include <iostream>
#include <string>
#include <utility>
#include <vector>
// Formats a double the way JSON.stringify does: shortest round-trip form, null for NaN or infinity.
std::string num(double x) {
if (!std::isfinite(x)) return "null";
char buffer[32];
auto [end, error] = std::to_chars(buffer, buffer + sizeof buffer, x);
(void)error;
return std::string(buffer, end);
}
std::string quote(const std::string& text) {
std::string out = "\"";
for (char c : text) {
if (c == '"' || c == '\\') out += '\\';
out += c;
}
return out + "\"";
}
// Indents an already formatted JSON value by one level.
std::string nested(const std::string& json) {
std::string out;
for (char c : json) {
out += c;
if (c == '\n') out += " ";
}
return out;
}
std::string object(const std::vector<std::pair<std::string, std::string>>& fields) {
if (fields.empty()) return "{}";
std::string out = "{";
for (std::size_t i = 0; i < fields.size(); ++i) {
out += i == 0 ? "\n " : ",\n ";
out += quote(fields[i].first) + ": " + nested(fields[i].second);
}
return out + "\n}";
}
// Ordered (Low < Medium < High), but a label, not a measured distance.
enum class RiskGrade { Low, Medium, High };
std::string label(RiskGrade grade) {
switch (grade) {
case RiskGrade::Low: return "low";
case RiskGrade::Medium: return "medium";
case RiskGrade::High: return "high";
}
return "";
}
struct Payment {
double amount;
std::string channel;
RiskGrade riskGrade;
bool flagged;
};
struct PaymentSummary {
double amount;
RiskGrade grade;
};
PaymentSummary lesson022() {
const Payment p{50, "card", RiskGrade::Medium, false};
const PaymentSummary result{p.amount, p.riskGrade};
return result;
}
int main() {
const PaymentSummary result = lesson022();
std::cout << object({
{"amount", num(result.amount)},
{"grade", quote(label(result.grade))}
}) << "\n";
}
No browser runner for C++ yet
Read the code here, then run it in your own toolchain or a ready-made cloud workspace.
Expected output
{
"amount": 50,
"grade": "medium"
}//! Fintech Math Bootcamp · Lesson 022 of 120
//! Numeric, Categorical, Ordinal, and Binary Variables
//! Module 03: Data, Variables, Samples, and Measurement
//!
//! Scenario: A risk grade is ordered, but not a measured distance
//! Rule: numeric · categorical · ordinal · binary
//!
//! Try it: Can we average customer IDs to describe a typical customer?
//!
//! Lesson article: https://thefintechbuilder.com/financial-mathematics-statistics-and-data-foundations/data-variables-samples-and-measurement/numeric-categorical-ordinal-and-binary-variables/
//! Free course: https://courses.thefintechbuilder.com
//! Synthetic teaching example, not financial advice or a production library.
//!
//! Run it: rustc main.rs && ./main
/// Ordered (Low < Medium < High), but a label, not a measured distance.
#[allow(dead_code)] // only Medium is used in this example
#[derive(Clone, Copy, PartialEq, PartialOrd)]
enum RiskGrade {
Low,
Medium,
High,
}
impl RiskGrade {
fn as_str(self) -> &'static str {
match self {
RiskGrade::Low => "low",
RiskGrade::Medium => "medium",
RiskGrade::High => "high",
}
}
}
#[allow(dead_code)] // channel and flagged are part of the record but not of the summary
struct Payment {
amount: f64,
channel: String,
risk_grade: RiskGrade,
flagged: bool,
}
struct PaymentSummary {
amount: f64,
grade: RiskGrade,
}
fn lesson022() -> PaymentSummary {
let p = Payment {
amount: 50.0,
channel: "card".to_string(),
risk_grade: RiskGrade::Medium,
flagged: false,
};
let result = PaymentSummary { amount: p.amount, grade: p.risk_grade };
result
}
fn main() {
let result = lesson022();
println!(
"{}",
object(&[
("amount", num(result.amount)),
("grade", quote(result.grade.as_str())),
])
);
}
/// Formats a number the way JSON.stringify does: shortest round-trip form, null for NaN or infinity.
fn num(x: f64) -> String {
if x.is_finite() {
format!("{}", x)
} else {
"null".to_string()
}
}
fn quote(text: &str) -> String {
format!("\"{}\"", text.replace('\\', "\\\\").replace('"', "\\\""))
}
/// Indents an already formatted JSON value by one level.
fn nested(json: &str) -> String {
json.replace('\n', "\n ")
}
fn object(fields: &[(&str, String)]) -> String {
if fields.is_empty() {
return "{}".to_string();
}
let lines: Vec<String> = fields
.iter()
.map(|(key, value)| format!(" {}: {}", quote(key), nested(value)))
.collect();
format!("{{\n{}\n}}", lines.join(",\n"))
}
No browser runner for Rust yet
Read the code here, then run it in your own toolchain or a ready-made cloud workspace.
Expected output
{
"amount": 50,
"grade": "medium"
}/**
* Fintech Math Bootcamp · Lesson 022 of 120
* Numeric, Categorical, Ordinal, and Binary Variables
* Module 03: Data, Variables, Samples, and Measurement
*
* Scenario: A risk grade is ordered, but not a measured distance
* Rule: numeric · categorical · ordinal · binary
*
* Try it: Can we average customer IDs to describe a typical customer?
*
* Lesson article: https://thefintechbuilder.com/financial-mathematics-statistics-and-data-foundations/data-variables-samples-and-measurement/numeric-categorical-ordinal-and-binary-variables/
* Free course: https://courses.thefintechbuilder.com
* Synthetic teaching example, not financial advice or a production library.
*
* Run it: dotnet run (inside a console project that holds this Program.cs)
*/
using System.Text.Json;
var jsonOptions = new JsonSerializerOptions { WriteIndented = true, PropertyNamingPolicy = JsonNamingPolicy.CamelCase };
Console.WriteLine(JsonSerializer.Serialize(Lesson022(), jsonOptions));
static PaymentSummary Lesson022()
{
var p = new Payment(Amount: 50, Channel: "card", RiskGrade: RiskGrade.Medium, Flagged: false);
var result = new PaymentSummary(p.Amount, p.RiskGrade.ToString().ToLowerInvariant());
return result;
}
// Ordered (Low < Medium < High), but a label, not a measured distance.
enum RiskGrade { Low, Medium, High }
record Payment(double Amount, string Channel, RiskGrade RiskGrade, bool Flagged);
record PaymentSummary(double Amount, string Grade);
No browser runner for C# yet
Read the code here, then run it in your own toolchain or a ready-made cloud workspace.
Expected output
{
"amount": 50,
"grade": "medium"
}Prefer your own machine? Every file is in the course repository · open it in Codespaces.
Lesson notes
The rule
numeric · categorical · ordinal · binary