Displaying n with n

JavaScript (ES6), 88 bytes

f=
n=>`019
2 3
459
6 7
889`.replace(/\d/g,c=>[2,18,142,96,130,131,698,4,146][c]>>n&1?` `:n)
<input type=number min=0 max=9 oninput=o.textContent=f(this.value)><pre id=o>

The numbers encode which squares contain spaces for a given digit e.g. the bottom left corner has a value of 146 because the 1, 4 and 7 don't use it and 146 = 2¹ + 2⁴ + 2⁷.


05AB1E, 40 39 38 bytes

•Y¤ŸèK'¦ú’ò™^N•4B5ô¹èvð¹«5714yè8+b¦Sè,

Try it online!

Explanation

•Y¤ŸèK'¦ú’ò™^N•            # the compressed string "318975565561233953387608032537"

4B                         # convert to base-4
  5ô                       # split into strings of size 5
    ¹è                     # get the string at index <input>
      v                    # for each digit y in string
          5714yè           # get the digit in 5714 at index y
                8+         # add 8
                  b        # convert to binary
                   ¦       # remove the leading 1
       𹫠         Sè     # with each digit in the binary number, 
                           # index into the string " <input>"   
                      ,    # print with newline

Japt, 43 bytes

"Ýûÿ©ÿßY÷ß"®c s4äëAU ¬£2839¤ë4X÷d0S1U

Contains some unprintables. Try it online!

Tallies: 13 bytes of compressed data, 9 bytes to decompress it, and 21 bytes to form the output.

Explanation

Ungolfed code:

"Ýûÿ©ÿßY÷ß"®   c s4à ¤  ëAU ¬ £  2839¤  ë4Xà ·  d0S1U
"Ýûÿ©ÿßY÷ß"mZ{Zc s4} s2 ëAU q mX{2839s2 ë4X} qR d0S1U

There are exactly 4 different row possibilities: (# represents a digit)

#  
  #
# #
###

Thus, each number can be stored as a set of five base-4 digits. Since each number can be then stored in 10 bits, the total is 100 bits, which corresponds to 13 bytes. I'll skip the compression process and instead explain the decompression.

mZ{Zc s4} 

mZ{     }  // Replace each character Z in the compressed string with the following:
   Zc      //   Take the char-code of Z.
      s4   //   Convert to a base-4 string.

After decompression, the 13-byte compressed string looks like this:

3131332333332111200122213333313321011121213133133133

Note that this would fail if any of the 4-digit runs started with 0, as the leading zeroes would be left off when s4 is run. We can fix this by having 0 represent #  , which only appears three times, and none of those fall at the start of a 4-digit run.

s2         // Slice off the first two chars of the result.

Okay, so in order to get our 50-digit string to compress nicely in chunks of 4, we had to add two extra digits. Adding them to the beginning of the string means we can chop them off with the one-byter ¤.

ëAU        // Take every 10th (A) char in this string, starting at index <input> (U).

Embarrassingly, Japt lacks a built-in for splitting a string into slices of length X. It does have a built-in for getting every Xth char, however, so we can store all the data by encoding all of the top rows first, then all of the second rows, etc.

So now we have the 5-digit string encoding the digit we want to create, e.g. 32223 for 0.

q mX{2839s2 ë4X} qR
q                    // Split the resulting string into chars.
  mX{          }     // Replace each char X with the result of this function:
     2839s2          //   Convert the magic number 2839 to a binary string.
            ë4X      //   Take every 4th char of this string, starting at index X.
                 qR  // Join the result with newlines.

To explain the magic number, refer back to the four distinct rows. If you replace # with 1 and   with 0, you get

100
001
101
111

Transposing this and then joining into a single string gives us 101100010111. Convert to decimal and, voilà, you have 2839. Reversing the process maps the digits 0123 into the four binary rows shown above.

Almost done! Now all that's left to do is add in the spaces and digits:

d0S1U      // In the resulting string, replace 0 with " " (S) and 1 with <input> (U).

And presto, implicit output takes care of the rest. I'm sorry this explanation is so long, but I don't see any real way to golf it without making it less understandable (if it is understandable...)