【问题标题】:Spread data into new columns, while also summarizing (adding) values - R or SQL将数据分散到新列中,同时汇总(添加)值 - R 或 SQL
【发布时间】:2019-03-06 15:40:51
【问题描述】:

我有一张如下所示的表格:

ID    YEAR    SOURCE    VALUE
 1    2014        AV       15
 1    2014        OV       25
 1    2015        AV       87
 2    2014        AX       44
 2    2015        AZ       32
 2    2015        NL        2
 3    2011        OV      104

我想重新构建表格以提供一个新列,其中汇总了源 AV、AX 和 NL 提供的 VALUE,以及另一个新列,其中给出了来自 OV 的值。例如,上面的代码如下所示:

ID    YEAR    AV+AX+NL    OV
 1    2014          15    25
 1    2015          87    NA
 2    2014          44    NA
 2    2015          32    NA
 3    2011          NA   104

我想在 R 中执行此操作,但如果更简单,可以使用 SQL。到目前为止,我一直在尝试结合 tidyverse 中的“summarise”和“mutate”命令来创建我的新列,但我无法找到一种方法来仅对某些 SOURCE 值而不是所有值求和。

非常感谢任何帮助

【问题讨论】:

  • 试试library(dplyr);df1 %>% group_by(ID, YEAR) %>% summarise(AV_AX_NL = sum(VALUE[SOURCE %in% c("AV", "AX", "NL")]), OV = sum(VALUE[SOURCE == "OV"]))
  • SOURCE == "AZ" 的记录呢?

标签: r sql-server dplyr


【解决方案1】:

非常简单的 SQL Server 查询。您所要做的就是按条件有条件地求和。

SELECT ID, [YEAR]
    , SUM(CASE WHEN SOURCE IN ('AV', 'AX', 'NL') THEN [VALUE] ELSE NULL END) [AV+AX+NL]
    , SUM(CASE WHEN SOURCE = 'OV' THEN [VALUE] ELSE NULL END) [OV]
FROM src
GROUP BY ID, [YEAR]
ORDER BY ID, [YEAR]

结果:

| ID | YEAR | AV+AX+NL | OV   |
+----+------+----------+------+
| 1  | 2014 | 15       | 25   |
| 1  | 2015 | 87       | NULL |
| 2  | 2014 | 44       | NULL |
| 2  | 2015 | 2        | NULL |
| 3  | 2011 | NULL     | 104  |

我最初使用 0 作为 case 中的条件不匹配时的替代值。但是,如果您希望在没有匹配项时显示 NULL 而不是 0,则需要将替代值更改为 NULL。如果仅将 NULL 值传递给聚合函数,则将返回 NULL。

需要注意的是,在 SUM 中使用 NULL 而不是 0 会产生警告:Null 值被聚合或其他 SET 操作消除。否则一切都很好。

编辑

那个 NULL 警告让我很困扰。产生相同结果的另一种方法是转换 SOURCE 列,以便将值 'av'、'ax'、'nl' 转换为 'av+ax+nl',然后使用 pivot 通过'av+ax+nl' 的源值。

SELECT pvt.ID, pvt.[YEAR], pvt.[AV+AX+NL], pvt.OV
FROM (
    SELECT ID, [YEAR], [VALUE]
        , CASE WHEN SOURCE IN ('AV', 'AX', 'NL') THEN 'AV+AX+NL' ELSE SOURCE END SOURCE2
    FROM src
) src2
PIVOT (
    SUM([VALUE])
    FOR SOURCE2 IN ([AV+AX+NL], [OV])
) pvt
ORDER BY ID, [YEAR]

【讨论】:

  • 为什么投反对票?这正是 O.P. 想要的结果?
  • 我不确定(不是我投了反对票)。我认为如果我用 NULL 替换零
  • @rw2,我将零更改为空。这确实会发出警告:Null 值被聚合或其他 SET 操作消除,但查询结果有效。
【解决方案2】:

一个选项是dcast 来自data.table

library(data.table)
dcast(setDT(df1), ID + YEAR ~ SOURCE %in% c("AV", "AX", "NL"),
                value.var = "VALUE", sum)

【讨论】:

  • 谢谢 - 这很好用,而且似乎比我的数据集的 dplyr 方法快很多
【解决方案3】:

Sql server 上有多种方法可以做到这一点,这是一种

WITH C AS(
    SELECT ID
          ,YEAR
          ,SUM(VALUE) AS [AVAXNL]
    FROM TABLE_1
    WHERE SOURCE IN('AV','AX','NL')
    GROUP BY ID,YEAR

),D AS(
    SELECT ID
          ,YEAR
          ,SUM(VALUE) AS [OV]
        FROM TABLE_1
    WHERE SOURCE IN('AV','AX','NL')
    GROUP BY ID,YEAR
)
SELECT  ISNULL(C.ID,D.ID) AS ID
       ,ISNULL(C.YEAR,D.YEAR) AS YEAR
       ,C.AVAXNL
       ,D.OV
FROM C
FULL JOIN D ON (C.ID = D.ID AND C.YEAR = D.YEAR)

您还可以旋转表格并添加每一行。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-10-27
    • 1970-01-01
    • 1970-01-01
    • 2021-07-07
    • 2013-03-10
    • 1970-01-01
    • 2021-04-23
    • 2015-07-26
    相关资源
    最近更新 更多