The documentation on the working of d3.format is complete but could use some more examples for novice users of javascript/d3. The goal of this document is to both offer an examplified tutorial as well as a small tool to help make this part of the d3 library more clear. If you are viewing this on a wide screen device you can use the format editor to the left to check live format output.

An Empty Formatter

The d3.format function takes a string as input and returns a function that converts a number to a string. It's goal is to help display numbers in the right format using a sort of 'regex-like' syntax. You can save a formatter in a variable or you can use the formatter directly.

One could save the formatter in a variable.

var formatter = d3.format("");
formatter(2)

Or create it and immediately use it.

d3.format("")(2);

Both return a string "2".

The string that the formatter needs as input need to follow the following specification:

[[fill]align][sign][symbol][0][width][,][.precision][type]

During the examples I will focus on what part of the specification we are using throughout the tutorial.

Simple types

At the very end of the format input string you can place a type.

[[fill]align][sign][symbol][0][width][,][.precision][type]

Exponential Numbers "e"

d3.format("e")(2000);
d3.format("e")(2000.0);
d3.format("e")(20003010);
d3.format("e")(0.000001);

An exponential type will show the amount of 10-exponents that the number contains. In the background this calls the .toExponential method on the number that the formatter receives.

Integers "d"

d3.format("d")(20);
d3.format("d")(1000.0);
d3.format("d")(1000.000001);
d3.format("d")(-1.12);

This was confusing for me in the beginning because I assumed that "d" stood for double. It does the exact opposite. It ignores non-integer values.

Rounded Percentage %

d3.format("%")(1);
d3.format("%")(0.999);
d3.format("%")(+0.12);
d3.format("%")(-0.12);

This multiplies the number times 100 and appends a "%" symbol at the end of the string.

Scientific Prefix "s"

Converts numbers to SI units.

d3.format("s")(1000);
d3.format("s")(0.000001);
d3.format("s")(1000);

This can be combined with a string.

d3.format("s")(1000) + 'm';
d3.format("s")(0.000001) + 'g';
d3.format("s")(25) + 'ms';
This can be tried out in de console for full output.

Uncommon Types

I've never felt the need for these types of numbers in my visualisations but for completeness you should also be aware of these types.

Binary Format

Convert to base two number.

d3.format("b")(1);
d3.format("b")(8)
d3.format("b")(16)
d3.format("b")(2012)

Octal Format

Convert to base 8 number.

d3.format("o")(1)
d3.format("o")(8)
d3.format("o")(16)
d3.format("o")(2012)

Hexadecimal Format

Convert to base 16 number.

d3.format("x")(17)
d3.format("x")(2012)
d3.format("X")(17)
d3.format("X")(2012)

Note, use "x" for lowercase and "X" for capital hexnumber.


Unicode Format

Any unicode character is mapped to a number. Formatting from unicode table index number to character is done via "c".

d3.format("c")(1000)

This also means that you can go through the entire unicode list if you are inclined. The first 1001 can be seen via;

d3.range(1001).map(d3.format("c"))

Types with Precision

Thusfar we have only discussed types. Certain types require a precision paramters to be passed along.

[[fill]align][sign][symbol][0][width][,][.precision][type]

General "g"

d3.format("g")(2000);
d3.format("g")(2000.0);
d3.format("g")(2000.03010);
d3.format("g")(0.01012);

With Precision

d3.format(".1g")(0.987654);
d3.format(".2g")(0.987654);
d3.format(".3g")(0.987654);

A precision type provides precision total length numerical output. This calls the .toPrecision method on the number that the formatter receives.

Fixed "f"

d3.format("f")(2000);
d3.format("f")(2000.0);
d3.format("f")(2000.03010);
d3.format("f")(0.01012);

With Precision

d3.format(".1f")(0.987654);
d3.format(".2f")(0.987654);
d3.format(".3f")(0.987654);

A fixed type provides precision length after the decimal point. In the background this calls the .toFixed method on the number that the formatter receives.

Rounded "r"

d3.format("r")(2000);
d3.format("r")(2000.0);
d3.format("r")(2000.03010);
d3.format("r")(0.01012);

With Precision

d3.format(".1r")(0.987654);
d3.format(".2r")(0.987654);
d3.format(".3r")(0.987654);

An general type will round the number to a fixed number. In the background this calls the .toFixed method on the number that the formatter receives.

Difference

These three methods are very similar. To emphesize the minor differences:

d3.format(".4g")(3.14159); //"3.142"
d3.format(".4f")(3.14159); //"3.1416"

Thousands Seperator

[[fill]align][sign][symbol][0][width][,][.precision][type]

Especially when dealing with monetary values a thousands seperator might be useful. The seperator can be combined with anything we have just discussed.

d3.format(",")(1000000);    //"1,000,000"
d3.format(",")(1010101);    //"1,010,101"
d3.format(",.4g")(1010101); //"1.010e+6"
d3.format(",.4e")(1010101); //"1.0101e+6"
d3.format(",.4f")(1010101); //"1.0101e+6"
d3.format(".2f")(10101);    //"10,101.00"

Width

[[fill]align][sign][symbol][0][width][,][.precision][type]

If you want you can specify a minimum width that the output string of the formatter needs to have. This might be usefull if you want to list thousands numbers on top of eachother in a clear overview.

d3.format("8")(1);      //"       1"
d3.format("8,.2f")(1);  //"    1.00"
d3.format("8g")(1e6);   //" 1000000"

Note that the string parser will recognize precision if it is preceeded by a "." or will otherwise be recognized as a width. If the precision will cause the output to be larger than the specified with then the width is ignored. If no width is passed to the format then it is determined by the content.

Zero Padding

[[fill]align][sign][symbol][0][width][,][.precision][type]

If the width parameter is prepended with a 0 then zeros will be added in front of the string.

d3.format("8")(1234);          //"    1234"
d3.format("08")(1234);         //"00001234"
d3.format("08.2f")(123.456);   //"00123.46"
d3.format("08.3f")(123.456);   //"0123.456"

Be aware that you need to be rather aware of what you are doing. If you combine the thousands seperator while you are prepending zeroes then you might end up with something you don't want.

d3.format("09,")(123456);      //"0,123,456"

Symbols

According to the docs symbols can be either a currency that is determined by your locale or a base for binary, octal or hexagonal numbers.

[[fill]align][sign][symbol][0][width][,][.precision][type]

The currency works pretty straightforward.

d3.format("$,")(1250);         //"$1,250"
d3.format("$,.2f")(1250);      //"$1,250.00"

For binary, octal, or hexadecimal output, prefix by 0b, 0o, or 0x, respectively. The # character can be used to force the type character as part of the output.

d3.format("0b")(125);  //"1111101"
d3.format("0o")(125);  //"175"
d3.format("0x")(125);  //"7d"
d3.format("#0b")(125);  //"0b1111101"
d3.format("#0o")(125);  //"0o175"
d3.format("#0x")(125);  //"0x7d"

Signs

[[fill]align][sign][symbol][0][width][,][.precision][type]

Symbols are characters that determine how to view negative/postive values. The documentation is clear on how a sign can be used, it can be:

  • "-" - indicating that a sign should be used only for negative numbers. (This is the default.)
  • "+" - indicating that a sign should be used for both positive and negative numbers.
  • " " - indicating that a leading space should be used on positive numbers, and a minus sign on negative numbers.
d3.format("+")(125);  //"+125"
d3.format("+")(-125); //"-125"
d3.format("-")(125);  //"125"
d3.format("-")(-125); //"-125"
d3.format(" ")(125);  //" 125"
d3.format(" ")(-125); //"-125"

Alignment and Fill

[[fill]align][sign][symbol][0][width][,][.precision][type]

You can also align the formatter output string with any character you want as long as it isn't { or }. You will need to tell the formatter how you want to align characters and what character to use as the fill. The fill character would need to preseed an alignment indicator:

  • "<" - left alignment
  • ">" - right alignment
  • "^" - center alignment

Here are some more examples that might help explain.

d3.format("4>8")(1); //"44444441"
d3.format("4^8")(1); //"44441444"
d3.format("4<8")(1); //"14444444"

What we are basically saying is that the output string needs 8 characters and requires a certain alignment. The character that we will use is 4 and depending on the alignment it will be added in front, around or after the number passed to the formatter.

Conclusion

Hopefully this guide has helped you understand the format syntax of d3 a bit better. To further challange yourself feel free to use the lefthand tool for some advanced explorations.

These more advanced exercizes might help to get you started on more advanced formats:

  1. Suppose that own drive a car and we know that it has driven 1231542.0431 meters and we want to know how many kilometer the car has driven, what would the appropriate formatter be?
  2. What format would the most clean to show dollars and cents on an invoice?
  3. What will d3.format("4>100")("")do?
  4. Why is there no difference between d3.format("e") and d3.format(",e")?

{% endblock body %}