【问题标题】:R ReConstruct DataFrameR重构数据框
【发布时间】:2020-03-14 14:57:29
【问题描述】:
data1=data.frame("grade"=c(rep(1:3,6)),
                "class" = c(rep(c(rep('a',3),rep('b',3)),3)),
"score"=c(rep(c('p','p','p','s','s','s','q','q','q'),2)),
"p"=c(-9:8),
"s"=c(1:18),
"q"=c(21:38))


data2=data.frame("grade"=c(rep(1:3,6)),
                  "class" = c(rep(rep('a',3),rep('b',3),3)),
                "pp"=c(-9,-8,-7,0,1,2),
                "ps"=c(1,2,3,10,11,12),
                "pq"=c(21,22,23,30,31,32),
                "sp"=c(-6,-5,-4,3,4,5),
                "ss"=c(4,5,6,13,14,15),
                "sq"=c(24,25,26,33,34,35),
                "qp"=c(-3,-2,-1,6,7,8),
                "qs"=c(7,8,9,16,17,18),
                "qq"=c(27,28,29,36,37,38))

我拥有的是data1,我想做data2。我的英语不太好,所以我制作了这两个示例数据框来展示我想要的。基本上是将'data1'中的'score'与data1中的列名'p'和'q'和'q'结合起来创建'data2'。

我有大量的学区数据,所以如果可能的话,希望有一个快速的 data.table 解决方案。也有兴趣查看 dplyr 或其他简单的解决方案!

然后我想知道如何按等级和'class' ggplot 'data2' [pp-qq] 的所有列

dcast(setDT(data1),grade + class + rowid(score) ~ score, value.var = c('p', 's', 'q'), sep="")[, score := NULL][]

希望分两步输出,终极愿望是一个在底部,一个在顶部是中间-

___________________________________________________________________ 一位成员在重铸数据框时给了我一个非常好的答案:

data1=data.frame("grade"=c(rep(1:3,6)),
                 "class" = c(rep(c(rep('a',3),rep('b',3)),3)),
                 "score"=c(rep(c('p','p','p','s','s','s','q','q','q'),2)),
                 "p"=c(-9:8),
                 "s"=c(1:18),
                 "q"=c(21:38))


d2=dcast(melt(setDT(data1), id.var = 1:3)[, c('score', 'variable') := 
                                         lapply(.SD, function(x) setNames(c(3, 5, 9), c('p', 's', 'q'))[x]),
                                       .SDcols = c('score', 'variable')],grade + class ~ 
        paste0('x', score, variable), value.var = 'value')

完美运行。然而,在我的应用程序中,我有更多的变量。当我什至只添加 1 时,我打破了它:

data1=data.frame("col1"=c(1),
  "grade"=c(rep(1:3,6)),
                 "class" = c(rep(c(rep('a',3),rep('b',3)),3)),
                 "score"=c(rep(c('p','p','p','s','s','s','q','q','q'),2)),
                 "p"=c(-9:8),
                 "s"=c(1:18),
                 "q"=c(21:38))


d2=dcast(melt(setDT(data1), id.var = 1:3)[, c('score', 'variable') := 
                                         lapply(.SD, function(x) setNames(c(3, 5, 9), c('p', 's', 'q'))[x]),
                                       .SDcols = c('score', 'variable')], col1 + grade + class ~ 
        paste0('x', score, variable), value.var = 'value')

[.data.table 中的错误(melt(setDT(data1), id.var = 1:3), , :=(c("score", : .SDcols 的某些项目不是列名:[score] 在 另外:警告消息:在 melt.data.table(setDT(data1), id.var = 1:3) : 'measure.vars' [score, p, s, q] 并不都是同一类型。 按层次顺序,熔断数据值列的类型为 '特点'。所有不是“字符”类型的度量变量都将是 也被胁迫。查看 ?melt.data.table 中的详细信息以了解有关强制的更多信息。

也许有一种方法可以减少破坏的可能性?非常感谢您的帮助!

【问题讨论】:

  • @akrun 有什么想法吗?
  • @Ronak Shah 有什么想法吗?
  • 这些值 x53、x35 是否互换了
  • 我看到一些值不正确。可以请您检查预期的
  • @akrun 我很感激你!

标签: r dplyr data.table


【解决方案1】:

有了tidyverse,我们可以做到

library(dplyr)
library(tidyr)
library(data.table)
data1 %>%
   mutate(rn = rowid(score)) %>% 
   pivot_wider(names_from = score, values_from = c('p', 's', 'q'), 
         names_sep="") %>%
    select(-rn)
# A tibble: 6 x 11
#  grade class    pp    ps    pq    sp    ss    sq    qp    qs    qq
#  <int> <fct> <int> <int> <int> <int> <int> <int> <int> <int> <int>
#1     1 a        -9    -6    -3     1     4     7    21    24    27
#2     2 a        -8    -5    -2     2     5     8    22    25    28
#3     3 a        -7    -4    -1     3     6     9    23    26    29
#4     1 a         0     3     6    10    13    16    30    33    36
#5     2 a         1     4     7    11    14    17    31    34    37
#6     3 a         2     5     8    12    15    18    32    35    38

或使用data.table

library(data.table)
dcast(setDT(data1), grade + class + rowid(score) ~ score,
     value.var = c('p', 's', 'q'), sep="")[, score := NULL][]
#   grade class pp pq ps sp sq ss qp qq qs
#1:     1     a -9 -3 -6  1  7  4 21 27 24
#2:     1     a  0  6  3 10 16 13 30 36 33
#3:     2     a -8 -2 -5  2  8  5 22 28 25
#4:     2     a  1  7  4 11 17 14 31 37 34
#5:     3     a -7 -1 -4  3  9  6 23 29 26
#6:     3     a  2  8  5 12 18 15 32 38 35

如果我们要替换列名,使用命名向量来匹配替换

out <- dcast(setDT(data1), grade + class + rowid(score) ~ 
      setNames(c(33, 55, 99), c('p', 's', 'q'))[score],
     value.var = c('p', 's', 'q'), sep="")[, score := NULL][]
setnames(out, 3:ncol(out), sub("^.", "x", names(out)[3:ncol(out)]))
out
#   grade class x33 x55 x99 x33 x55 x99 x33 x55 x99
#1:     1     a  -9  -3  -6   1   7   4  21  27  24
#2:     1     a   0   6   3  10  16  13  30  36  33
#3:     2     a  -8  -2  -5   2   8   5  22  28  25
#4:     2     a   1   7   4  11  17  14  31  37  34
#5:     3     a  -7  -1  -4   3   9   6  23  29  26
#6:     3     a   2   8   5  12  18  15  32  38  35

对于更新的示例,我们还需要通过 'class' 获取序列

out <- dcast(setDT(data1), grade + class + rowid(class, score) ~ 
       setNames(c(33, 55, 99), c('p', 's', 'q'))[score],
      value.var = c('p', 's', 'q'), sep="")[, class1 := NULL][]
setnames(out, 3:ncol(out), sub("^.", "x", names(out)[3:ncol(out)]))
out
#   grade class x33 x55 x99 x33 x55 x99 x33 x55 x99
#1:     1     a  -9  -3   3   1   7  13  21  27  33
#2:     1     b   0   6  -6  10  16   4  30  36  24
#3:     2     a  -8  -2   4   2   8  14  22  28  34
#4:     2     b   1   7  -5  11  17   5  31  37  25
#5:     3     a  -7  -1   5   3   9  15  23  29  35
#6:     3     b   2   8  -4  12  18   6  32  38  26

更新

setDT(data1)[, score := setNames(c(3, 5, 9), c('p', 's', 'q'))[score]]
setnames(data1, c('p', 's', 'q'), as.character(c(3, 5, 9)))
out <-  dcast(setDT(data1), grade + class + rowid(class, score) ~ score,
     value.var = c('3', '5', '9'), sep="")[, class1 := NULL][]
setnames(out, 3:ncol(out), paste0("x", names(out)[3:ncol(out)]))

或者另一个选项是melt/dcast

dcast(melt(setDT(data1), id.var = 1:3)[, c('score', 'variable') := 
 lapply(.SD, function(x) setNames(c(3, 5, 9), c('p', 's', 'q'))[x]),
 .SDcols = c('score', 'variable')], grade + class ~ 
     paste0('x', score, variable), value.var = 'value')
#   grade class x33 x35 x39 x53 x55 x59 x93 x95 x99
#1:     1     a  -9   1  21  -3   7  27   3  13  33
#2:     1     b   0  10  30   6  16  36  -6   4  24
#3:     2     a  -8   2  22  -2   8  28   4  14  34
#4:     2     b   1  11  31   7  17  37  -5   5  25
#5:     3     a  -7   3  23  -1   9  29   5  15  35
#6:     3     b   2  12  32   8  18  38  -4   6  26

【讨论】:

  • @bvowe 我还通过cumsum 发布了您其他问题的解决方案。可能。对你有用
  • 非常感谢!我实际上尝试了你的 data.table 解决方案,它给了我一些'NA'
  • 啊,我明白了,这是一个非常好的答案。我觉得它很有用;)
  • @bvowe 请使用melt/dcast 而不是我在理解完整问题之前创建的第一个
  • 完美!再次感谢,你真的非常有帮助。我学到了很多东西!
【解决方案2】:

您可以为此使用基本函数reshape。

我需要添加一个额外的变量 (unique) 来区分 data1 中的前 9 行和后 9 行。如果你不需要它,你可以在以后删除它。

data1$unique <- rep(1:2, each=9)

reshape(data=data1, 
        direction="wide",
        v.names=c("p","s","q"),
        timevar="score",
        idvar=c("grade","class","unique"),
        sep="")

   grade class unique pp sp qp ps ss qs pq sq qq
1      1     a      1 -9  1 21 -6  4 24 -3  7 27
2      2     a      1 -8  2 22 -5  5 25 -2  8 28
3      3     a      1 -7  3 23 -4  6 26 -1  9 29
10     1     a      2  0 10 30  3 13 33  6 16 36
11     2     a      2  1 11 31  4 14 34  7 17 37
12     3     a      2  2 12 32  5 15 35  8 18 38

【讨论】:

  • 非常感谢,现在说我想用数字表示 v.names,所以 p = 3 和 s = 5 和 q = 9。所以我有 x33 x35 x39 而不是 pp ps pq ?为了? @George Savva
猜你喜欢
  • 2021-03-01
  • 1970-01-01
  • 2017-11-02
  • 1970-01-01
  • 2014-03-10
  • 1970-01-01
  • 1970-01-01
  • 2014-11-09
  • 1970-01-01
相关资源
最近更新 更多