【问题标题】:Convert a table into a list of data frames in R将表格转换为R中的数据框列表
【发布时间】:2017-05-08 22:46:01
【问题描述】:

我有一个包含三个变量的数据框:分组变量 (Group) 和分类变量,指示组是否是新的 (New) 以及其条目是否拖欠 (Delinquent)。

以下是样本数据

df <- structure(list(Group = structure(c(1L, 1L, 1L, 2L, 2L, 2L, 3L, 3L, 3L, 4L, 4L, 5L, 6L, 7L), .Label = c("A", "B", "C", "D", "E", "F", "G"), class = "factor"), New = c(FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE), Delinquent = c(FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE)), .Names = c("Group", "New", "Delinquent"), class = "data.frame", row.names = c(NA, -14L))
#df

我正在尝试通过他们是否是新的来计算拖欠组的数量。为此,我将table 包裹在aggregate 周围的一个简单数据框上:

yo &lt;- table(aggregate(Delinquent ~ Group + New, data = df, FUN = max))

产生相当奇怪的输出,“table”类的对象

yo
#, , Delinquent = 0
#
#     New
#Group FALSE TRUE
#    A     0    0
#    B     0    0
#    C     1    0
#    D     0    1
#    E     1    0
#    F     0    1
#    G     0    0
#
#, , Delinquent = 1
#
#     New
#Group FALSE TRUE
#    A     1    0
#    B     0    1
#    C     0    0
#    D     0    0
#    E     0    0
#    F     0    0
#    G     1    0

输出似乎是我需要按其是否为新的状态来统计拖欠组的数量。通常,我将表格转换为数据框以直接与数据交互。但是,在这种情况下,我无法与输出的表对象交互或成功转换它。我尝试通过as.data.frameas.data.frame.matrix 将其转换为数据框,并通过as.listas.data.frame.list 将其转换为列表,但转换后的输出似乎不正确。使用as.data.frame.array 是我能想到的最好的方法,但我期待一个包含两个单独数据框的列表,每个数据框用于每个拖欠状态。有什么建议吗?

as.data.frame.array(yo)
#   FALSE.0 TRUE.0 FALSE.1 TRUE.1
# A       0      0       1      0
# B       0      0       0      1
# C       1      0       0      0
# D       0      1       0      0
# E       1      0       0      0
# F       0      1       0      0
# G       0      0       1      0

【问题讨论】:

    标签: r list dataframe aggregate tabular


    【解决方案1】:

    你应该使用as.data.frame.table

    如果你想把所有东西都放在一个data.frame

    as.data.frame.table(yo)
    
       Group   New Delinquent Freq
    1      A FALSE          0    0
    2      B FALSE          0    0
    3      C FALSE          0    1
    4      D FALSE          0    0
    5      E FALSE          0    1
    ...
    

    如果你说你想要data.frames的列表:

    (yolist <- apply(yo, 3, as.data.frame.table))
    
    $`0`
       Group   New Freq
    1      A FALSE    0
    2      B FALSE    0
    3      C FALSE    1
    4      D FALSE    0
    5      E FALSE    1
    ...
    
    $`1`
       Group   New Freq
    1      A FALSE    1
    2      B FALSE    0
    3      C FALSE    0
    4      D FALSE    0
    5      E FALSE    0
    ...
    
    sapply(yolist, class)
               0            1
    "data.frame" "data.frame"
    

    这很有效,因为您的表是 3 维数组。上面的行从一个按适当索引切片的表构造了一个 data.frame。

    【讨论】:

      【解决方案2】:

      要通过另一个方法来接近您的目标(新的或不存在的拖欠人数),您还可以使用 plyr 包中的 ddply:

      library(plyr)
      
      yo <- ddply(df, .(Group, New, Delinquent), summarize,
                   sum_in_group = length(Delinquent==TRUE)
                   )
      

      给予:

        Group   New Delinquent sum_in_group
      1     A FALSE      FALSE            1
      2     A FALSE       TRUE            2
      3     B  TRUE      FALSE            1
      4     B  TRUE       TRUE            2
      5     C FALSE      FALSE            3
      6     D  TRUE      FALSE            2
      7     E FALSE      FALSE            1
      8     F  TRUE      FALSE            1
      9     G FALSE       TRUE            1
      

      我知道这并不能直接回答您的表格问题,但我发现这个输出更容易处理我自己。

      编辑

      回应您的评论:类似

      yo <- ddply(df, .(Group, New), summarize,
                  Delinquent = max(Delinquent)
      );yo
      
        Group   New Delinquent
      1     A FALSE          1
      2     B  TRUE          1
      3     C FALSE          0
      4     D  TRUE          0
      5     E FALSE          0
      6     F  TRUE          0
      7     G FALSE          1
      

      拖欠列中的 1 表示该组至少拖欠一次。

      或者,也许您也想要一个合规列:

      plyr:

      library(plyr)
      ddply(df, .(Group, New), summarize,
                  delinquent = as.numeric(any(Delinquent)), 
                  compliant = as.numeric(!any(Delinquent))
      ) 
      

      dplyr:

      library(dplyr)
      as.data.frame(df %>% 
        group_by(Group, New) %>%
        summarize(
          delinquent = as.numeric(any(Delinquent)), 
          compliant = as.numeric(!any(Delinquent))
          )
      )
      

      两个输出:

        Group   New delinquent compliant
      1     A FALSE          1         0
      2     B  TRUE          1         0
      3     C FALSE          0         1
      4     D  TRUE          0         1
      5     E FALSE          0         1
      6     F  TRUE          0         1
      7     G FALSE          1         0
      

      【讨论】:

      • 嗯。我使用问题本身中创建的yo 得到不同的输出 - 我在那里做错了吗?我完全不精通data.table,所以如果我没有正确理解输出,我深表歉意。
      • 感谢这个替代策略。至于没有得到与原始帖子中相同的yo,只是为了澄清,data.table 包没有涉及。它使用了来自基础 R 的 table。无论哪种方式,您的 plyr 输出都会产生我正在寻找的东西,所以谢谢你。
      • 哦,我正在回复另一位用户关于我不太理解的评论(现已删除)。谢谢你的澄清!
      • 啊,实际上,我看错了上面的输出。 sum_in_group 输出不会产生我想要的东西。在所有组中,它应该总计有七个实例,例如 Karolis 答案中的 Freq 列。它更像是组内“最大”而不是组内“总和”(即我想知道拖欠组的数量,任何时候一个组拖欠,即使有一次,他们都被认为是拖欠,而他们' d 每次都需要合规才能被标记为“不拖欠”)。有没有办法编辑您的ddply 解决方案以获得更正的输出?
      • 明白了。编辑了我的答案,看看是否更接近,虽然我会说我喜欢@Karolis 的答案,所以如果它对你有用,那就太好了,我只是想提出一个替代方案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-11-14
      • 2015-04-16
      • 1970-01-01
      • 2021-10-17
      • 1970-01-01
      • 2015-11-30
      • 1970-01-01
      相关资源
      最近更新 更多