【问题标题】:Spreading row indices into columns in R将行索引传播到 R 中的列中
【发布时间】:2016-12-02 13:56:59
【问题描述】:

我在 R 中有一个数据框,格式如下:

> old.dat
       id type minDate maxDat eventNum
1    001    A     may   june        1
2    002    B     apr    oct        1
3    002    C     may    nov        2
4    002    B    july    dec        3

我想根据eventNum 将行转换为列。 eventNum 的最大值为 3,所以如果某些 ID 只有 1 个 eventNum,我希望它们填充 NA

目标:

      id type1 minDate1 maxDat1 eventNum1 type2 minDate2 maxDat2 eventNum2 type3 minDate3 maxDat3 eventNum3
1    001     A      may    june         1  <NA>     <NA>    <NA>        NA  <NA>     <NA>    <NA>        NA
2    002     B      apr     oct         1     C      may     nov         2     B     july     dec         3

这是一个引入起点的代码块。

old.dat <- data.frame(id = c("001","002","002","002"),
                      type = c("A","B","C","B"),
                      minDate = c("may","apr","may","july"),
                      maxDat = c("june", "oct", "nov", "dec"),
                      eventNum = c(1,1,2,3))

我写了一个 for 循环,但它相当慢,而且需要很长时间来翻阅我的数据集,所以任何更快的建议都会很棒。谢谢!

【问题讨论】:

  • 你的目标几乎是我能想象到的最糟糕的格式......无论如何,data.table 和 reshape2/tidyr 都提供了重塑功能。试试看。

标签: r dataframe data.table dplyr


【解决方案1】:

为什么?我不知道我是否能想象这种格式有用的情况,但这里有一种使用tidyr 的方法。

首先,我保存了一个新列名的列表,以便更轻松地组合在一起:

newCols <- c("type", "minDate", "MaxDat")

(我将在下面添加数字)。

然后,我 uniteing 为每个事件指定您想要的值,spreading 结果为每个 eventNum 获取一个新列,然后 separateing 将结果返回到单独的列中(并附加事件的编号)

old.dat %>%
  unite(toSpread, type, minDate, maxDat, sep = "::") %>%
  spread(eventNum, toSpread) %>%
  separate(`1`, paste0(newCols, "_1"), sep = "::") %>%
  separate(`2`, paste0(newCols, "_2"), sep = "::") %>%
  separate(`3`, paste0(newCols, "_3"), sep = "::")

返回:

   id type_1 minDate_1 MaxDat_1 type_2 minDate_2 MaxDat_2 type_3 minDate_3 MaxDat_3
1 001      A       may     june   <NA>      <NA>     <NA>   <NA>      <NA>     <NA>
2 002      B       apr      oct      C       may      nov      B      july      dec

这是一种替代方法,它首先将数据转换为长格式(使用gather),然后生成新的列名并进行传播。为新列分配因子级别的复杂mutate 行只需要对列进行排序并使用readr 中的parse_number 来提取事件编号。如果您对按字母顺序排序的输出列没有问题,则可以跳过该步骤。这种方法对于额外的事件编号是稳健的,因为它会自动为eventNum 中的每个唯一值添加事件。

old.dat %>%
  gather(Metric, Value, type, minDate, maxDat) %>%
  unite(newColHead, Metric, eventNum) %>%
  mutate(newColHead = factor(newColHead
                             , levels =
                               unique(newColHead) %>%
                               {.[order(parse_number(.))]}
                               )) %>%
  spread(newColHead, Value)

对于这个用例,输出与上述相同。

(而且,如果您想要证明这可能会更好的证据;请注意我的编辑——我最初错误地标记了事件编号 2/3。)

【讨论】:

  • 感谢您的帮助!我意识到格式远非最佳,但在我无法控制的情况下需要它。
最近更新 更多