[Saddam][1] has a smart solution, but it carries some weaknesses. Imagine a source named *'Fresno, CA'* (with comma in the string). `split_part()` would be fooled by the separator character in the string ...

To avoid such corner case problems and preserve original data types, use a (well-defined!) row type instead. You can create a composite type permanently with [`CREATE TYPE`][2] or register a temporary one with `CREATE TEMP TABLE`:

    CREATE TEMP TABLE defso (def numeric, so varchar);  -- once per session!
    
    SELECT country_code
         , country_name
         , (d14).def AS deflator_2014  -- note the parentheses!
         , (d14).so  AS source_2014
         , (d15).def AS deflator_2015
         , (d15).so  AS source_2015
         , (d16).def AS deflator_2016
         , (d16).so  AS source_2016
    FROM   crosstab (
        'SELECT country_code, country_name, year, (deflator, source)::defso
         FROM   deflator
         ORDER  BY 1'
      , 'SELECT generate_series(2014, 2016)::int2'
       ) AS ct (country_code int2
              , country_name text
              , d14 defso
              , d15 defso
              , d16 defso
       );

I also removed the unnecessary CTE and simplified a bit.

---

While dealing with only a hand full of years, you can do without `crosstab()` and use self-joins:

    SELECT country_code, country_name
         , d14.deflator AS deflator_2014
         , d14.source   AS source_2014
         , d15.deflator AS deflator_2015
         , d15.source   AS source_2015
         , d16.deflator AS deflator_2016
         , d16.source   AS source_2016
    FROM        (SELECT * FROM deflator WHERE year = int2 '2014') d14
    FULL   JOIN (SELECT * FROM deflator WHERE year = int2 '2015') d15 USING (country_code, country_name)
    FULL   JOIN (SELECT * FROM deflator WHERE year = int2 '2016') d16 USING (country_code, country_name)
    ORDER  BY country_code;

Using `FULL [OUTER] JOIN` since we can't assume a row for *every* combination of `(country_code, year)`. This way we get the same result as with the crosstab query above.

Including `country_name` in the join condition seems redundant, but if we don't, we have to use `COALESCE(d14.country_name, d15.country_name, d16.country_name) AS country_name` to defend against missing rows. This functionally dependent value shouldn't be in the table to begin with. Should be in a `country` table in a properly normalized schema. 

  [1]: https://dba.stackexchange.com/a/158236/3684
  [2]: https://www.postgresql.org/docs/current/static/sql-createtype.html