【问题标题】:get count and sum in same column in R在R中的同一列中获取计数和总和
【发布时间】:2019-09-04 17:05:00
【问题描述】:

我在下面提到了 R 中的数据框。

ID       Date         Type         Value
K-1      2018-01-01   A            4
K-2      2018-01-01   B            7
K-3      2018-01-01   C            12
K-4      2018-01-02   A            6
K-5      2018-01-02   A            4
K-6      2018-01-02   B            15
K-7      2018-01-02   B            10

我想了解如何转换下面给定所需数据帧中的数据帧,其中ABC 对于每个日期都应该是静态的,无论该特定类型在该日期是否可用.

另外,我想按日期统计ID组和Type,在<5的桶中(如果值在1-4之间),5-10(如果值在5到10之间) 和>10(如果值大于 10)。

sum 列应包含该特定日期和类型的总价值。

Count 列应包含按特定日期分组的ID 计数和Type

存储桶<55-10>10 应始终存在于所需的输出中,无论该存储桶的值是否可用。

此外,如何通过括号() 中的存储桶获取特定ID 组的总和,用逗号分隔2 个十进制值。 括号中 sum 的字体应小于 count 的字体(即如果<5 bucket 的 count 字体为 12,则括号中 sum 的字体应为 10)。 此外,如果特定桶中的计数为 0,则不需要以 (0.00) 作为值的括号。

必需的 DF

Date           Count      <5      5-10       >10      sum
2018-01-01      3         1 (4)    1 (7)      1 (12)   23
A               1         1 (4)    0          0        4
B               1         0        1 (7)      0        7
C               1         0        0          1 (12)   12
2018-01-02      4         1 (4)    2 (16)     1 (15)   35
A               2         1 (4)    1 (6)      0        10
B               2         0        1 (10)     1 (15)   25
C               0         0        0          0        0

我正在使用的代码(来自 SO):

library(tidyverse)

dat2 <- dat %>%
  mutate(Result = case_when(
    Value < 5                        ~"<5",
    Value >= 5 & Value <= 10         ~"5-10",
    Value > 10                       ~">10"
  )) %>%
  group_by(Date, Type, Result) %>%
  summarize(sum = sum(Value)) %>%
  mutate(Flag = 1L) %>%
  spread(Result, Flag, fill = 0L) %>%
  group_by(Date, Type) %>%
  summarize_all(list(~sum(.))) %>%
  ungroup() %>%
  complete(Date, Type)

dat2[is.na(dat2)] <- 0

dat3 <- dat2 %>% mutate(Count = rowSums(select(., -Date, -Type, -sum)))

dat4 <- dat3 %>%
  group_by(Date) %>%
  summarize_at(vars(-Type), list(~sum(.))) 

dat_final <- map2_dfr(split(dat4, f = dat4$Date),
                      split(dat3, f = dat3$Date),
                      ~bind_rows(.x %>% rename(Type = Date), 
                                 .y %>% select(-Date)))

dat_final2 <- dat_final %>%
  select(Date = Type, Count, `<5`, `5-10`, `>10`, sum)
dat_final2

【问题讨论】:

    标签: r dataframe dplyr data.table tidyr


    【解决方案1】:

    tables 包非常适合简洁地描述此类输出。首先创建计算列中显示的统计信息的函数。然后使用指定的tabular 公式。 LHS 是行,RHS 是列。 + 表示连接 + 两边描述的变量。

    sprintf 的输出可以通过例如更改格式字符串来改变。见?sprintf

    乳胶

    此外,如果tabtabular 命令的输出,那么latex(tab) 将创建一个乳胶版本,您可以通过插入乳胶命令进一步改变它。例如"%d \\tiny{(%d)}" 作为sprintf 格式的字符串将使乳胶输出中的括号部分更小。

    html

    如果您想要html 输出,然后使用刚刚定义的tab,那么html(tab) 会创建一个html 版本,该版本可以通过适当的html 标签进一步变化。例如"%d &lt;small&gt;(%d)&lt;/small&gt;" 作为sprintf 格式字符串将使html 输出中的括号部分更小。

    输入

    我们在末尾的注释中以可重复的形式提供输入 dat。下次请确保以可复制的形式提供输入。

    代码

    这主要再现了问题中显示的输出,并且比那里的代码更紧凑。

    library(tables)
    
    outstring <- function(x) if (length(x)) sprintf("%d (%d)", length(x), sum(x)) else 0
    `<5` <- function(x) outstring(x[x < 5])
    `5-10` <- function(x) outstring(x[x >= 5 & x <= 10])
    `>10` <- function(x) outstring(x[x > 10])
    
    tab <- 
      tabular(Date * (1 + Type) ~ (n=1) + Value * (`<5` + `5-10` + `>10` + sum), data = dat)
    

    给予:

                           Value                  
     Date                n <5    5-10   >10    sum
     2018-01-01      All 3 1 (4) 1 (7)  1 (12) 23 
                Type A   1 1 (4) 0      0       4 
                     B   1 0     1 (7)  0       7 
                     C   1 0     0      1 (12) 12 
     2018-01-02      All 4 1 (4) 2 (16) 1 (15) 35 
                Type A   2 1 (4) 1 (6)  0      10 
                     B   2 0     1 (10) 1 (15) 25 
                     C   0 0     0      0       0 
    

    注意

    dat <- 
    structure(list(ID = structure(1:7, .Label = c("K-1", "K-2", "K-3", 
    "K-4", "K-5", "K-6", "K-7"), class = "factor"), Date = structure(c(1L, 
    1L, 1L, 2L, 2L, 2L, 2L), .Label = c("2018-01-01", "2018-01-02"
    ), class = "factor"), Type = structure(c(1L, 2L, 3L, 1L, 1L, 
    2L, 2L), .Label = c("A", "B", "C"), class = "factor"), Value = c(4L, 
    7L, 12L, 6L, 4L, 15L, 10L)), class = "data.frame", row.names = c(NA, 
    -7L))
    

    更新

    tabular 类有一个 as.matrix 方法,我们可以对其执行简单的操作以产生以下输出:

    m <- as.matrix(tab)
    m2 <- cbind(paste0(m[, 1], sub("All", "", m[, 3])), m[, -(1:3)])[-1, ]
    setNames(as.data.frame(m2[-1, ]), m2[1, ])
    

    给予:

            Date n    <5   5-10    >10 sum
    1 2018-01-01 3 1 (4)  1 (7) 1 (12)  23
    2          A 1 1 (4)      0      0   4
    3          B 1     0  1 (7)      0   7
    4          C 1     0      0 1 (12)  12
    5 2018-01-02 4 1 (4) 2 (16) 1 (15)  35
    6          A 2 1 (4)  1 (6)      0  10
    7          B 2     0 1 (10) 1 (15)  25
    8          C 0     0      0      0   0
    

    【讨论】:

    • 收到错误Error in term2table(rows[[i]], cols[[j]], data, n) : Duplicate values: Date and Value
    • @user9211845 无法在答案中使用dat 重现错误。您可能需要显示导致错误的小示例的dput
    • @G.Grothendieck :仍然得到同样的错误,这是我的数据框structure(list(ID = c("CRX-1234", "CRX-4567", "CRX-1011" ), Date = c("2019-04-01", "2019-04-01", "2019-04-01"), Type = c("A", "B", "C"), Value = c(190000, 230000, 1110000 )), .Names = c("ID", "Date", " Type ", "Value"), row.names = c(NA, 3L), class = "data.frame")的dput
    • @G.Grothendieck:它工作但没有转换成数据框cannot coerce class ""tabular"" to a data.frame
    • @akrun:我在线程中提供了dput,输出不是所需的格式。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-02-24
    • 2020-09-29
    • 2017-07-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多