【问题标题】:Transform table to one-hot-encoding of single column value将表转换为单列值的 one-hot-encoding
【发布时间】:2017-08-10 18:43:30
【问题描述】:

我有一个包含两列的表格:

+---------+--------+
| keyword | color  |
+---------+--------+
| foo     | red    |
| bar     | yellow |
| fobar   | red    |
| baz     | blue   |
| bazbaz  | green  |
+---------+--------+

我需要在 PostgreSQL 中进行某种单热编码和转换表:

+---------+-----+--------+-------+------+
| keyword | red | yellow | green | blue |
+---------+-----+--------+-------+------+
| foo     |   1 |      0 |     0 |    0 |
| bar     |   0 |      1 |     0 |    0 |
| fobar   |   1 |      0 |     0 |    0 |
| baz     |   0 |      0 |     0 |    1 |
| bazbaz  |   0 |      0 |     1 |    0 |
+---------+-----+--------+-------+------+

是否可以只使用 SQL?关于如何开始的任何提示?

【问题讨论】:

  • one-hot encoding 是什么意思?
  • 您的“颜色”列表是否预先知道?
  • @PM77-1 是的,只有这四个。
  • @Siyual 是转换的名称,即将分类数据转换为数字,其中每个类别位于单独的列中。 quora.com/…
  • 然后对每个“颜色”使用CASE WHEN。如果keyword & color 对不是唯一的,则需要添加聚合。

标签: sql postgresql crosstab


【解决方案1】:

如果我理解正确的话,你需要条件聚合:

select keyword,
count(case when color = 'red' then 1 end) as red,
count(case when color = 'yellow' then 1 end) as yellow
-- another colors here
from t
group by keyword

【讨论】:

  • 不知道为什么它被否决了,它确实起到了作用。现在看起来很明显,谢谢。
  • 这确实符合原始问题的标准,但我正在寻找一种方法来为数据科学家动态地对 100 多列进行热编码。它基本上需要旋转每列的潜在值并动态地进行。希望有人已经写出了动态 SQL!
  • @njkroes,你有没有找到答案?我遇到了类似的情况,我希望编码的列列表可能会改变
  • @njfrazie 我最终只使用了一堆 IIF 语句来执行此操作,如此处所述。在您正在查看大量数据的情况下,您可以获取所有表示的答案并动态生成一些东西,但是除非您已经知道会发生什么,否则实际上没有办法动态地为一条记录做某事。在这种情况下,您只需写出此答案所暗示的所有预期结果。
【解决方案2】:

使用tablefunc 扩展和COALESCE() to fill all NULL fields 在您的测试用例中实现目标的另一种方法:

postgres=# create table t(keyword varchar,color varchar);
CREATE TABLE
postgres=# insert into t values ('foo','red'),('bar','yellow'),('fobar','red'),('baz','blue'),('bazbaz','green');
INSERT 0 5
postgres=# SELECT keyword, COALESCE(red,0) red, 
 COALESCE(blue,0) blue, COALESCE(green,0) green, 
 COALESCE(yellow,0) yellow 
 FROM crosstab(                         
  $$select keyword, color, COALESCE('1',0) as onehot from test01
    group by 1, 2 order by 1, 2$$,
  $$select distinct color from test01 order by 1$$)
 AS result(keyword varchar, blue int, green int, red int, yellow int);
 keyword | red | blue | green | yellow 
---------+-----+------+-------+--------
 bar     |   0 |    0 |     0 |      1
 baz     |   0 |    1 |     0 |      0
 bazbaz  |   0 |    0 |     1 |      0
 fobar   |   1 |    0 |     0 |      0
 foo     |   1 |    0 |     0 |      0
(5 rows)

postgres=# 

如果你只是为了得到psql下的结果:

postgres=# select keyword, color, COALESCE('1',0) as onehot from t
  --group by 1, 2 order by 1, 2
  \crosstabview keyword color
 keyword | red | yellow | blue | green 
---------+-----+--------+------+-------
 foo     |   1 |        |      |      
 bar     |     |      1 |      |      
 fobar   |   1 |        |      |      
 baz     |     |        |    1 |      
 bazbaz  |     |        |      |     1
(5 rows)

postgres=# 

【讨论】:

    【解决方案3】:

    要在具有大量列的表上使用此代码,请使用 Python 生成查询:

    1) 创建一个列表,其中包含您希望作为列名的唯一变量并将其导入 Python,例如:list

    for item in list:
     print('count(case when item=' +str(item)+ 'then 1 end) as is_'+str(item)+',')
    

    2) 复制输出(减去最后一行的最后一个逗号)

    3) 那么:

    select keyword,
    
    OUTPUT FROM PYTHON
    
    from t
    group by keyword
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-02-12
      • 1970-01-01
      • 2018-03-18
      • 2023-03-17
      • 2021-08-19
      • 2019-10-11
      • 2019-09-27
      相关资源
      最近更新 更多