使用R将一列提取为行,保留其他列

使用R将一列提取为行,保留其他列,r,dplyr,plyr,reshape2,tidyr,R,Dplyr,Plyr,Reshape2,Tidyr,我所拥有的: 我有一个如下所示的数据框: sequence foo model output real 1 3 a 12 12 1 3 b 29 12 1 3 c 10 12 1 3 d 38 12 1 3 e 10 12 2 3 a 38 15 2 3

我所拥有的:

我有一个如下所示的数据框:

sequence foo model output real
       1   3     a     12   12
       1   3     b     29   12
       1   3     c     10   12
       1   3     d     38   12
       1   3     e     10   12
       2   3     a     38   15
       2   3     b     10   15
       2   3     c     29   15
       2   3     d     56   15
       2   3     e     10   15
创建人:

d.test = data.frame(
  sequence = c(1, 1, 1, 1, 1, 2, 2, 2, 2, 2),
  foo = c(3, 3, 3, 3, 3, 3, 3, 3, 3, 3),
  model = c("a", "b", "c", "d", "e", "a", "b", "c", "d", "e"),
  output = c(12, 29, 10, 38, 10, 38, 10, 29, 56, 10),
  real = c(12, 12, 12, 12, 12, 15, 15, 15, 15, 15)
)
该模型预测每个给定的
序列
输出
,但
真实
输出也会沿每个序列记录

我需要什么:

我想转换数据,使
real
本身成为一个“模型”,即:

sequence foo model output
       1   3     a     12
       1   3     b     29
       1   3     c     10
       1   3     d     38
       1   3     e     10
       1   3  real     12
       2   3     a     38
       2   3     b     10
       2   3     c     29
       2   3     d     56
       2   3     e     10
       2   3  real     15
我如何使用
dplyr
tidyr
和他们的表亲来实现这一点

请注意,对于“好”的解决方案,不必:

  • 手动输入列索引
  • 手动指定所有不感兴趣的列,如
    foo
我所尝试的:

我尝试了以下方法,但感觉很笨拙:

unique(
  melt(d.test,
    id.vars = c("sequence", "foo"),
    measure.vars = c("real"),
    variable.name = "model",
    value.name = "output"
  )
)
现在,我必须从原始数据帧中删除
real
列,并附加我刚才所做的操作的行。这不是一个好的解决方案,因为除了
foo
列之外,我可能还想保留更多的列,然后我必须将它们指定为
id.vars

我会使用data.table:

library(data.table)
setDT(d.test)

d.test[, 
  rbind(.SD, .SD[1L][, `:=`(model = "real", output = real[1L])])
, by=sequence][, real := NULL][]

如果我不得不使用“诗句:

d.real = d.test %>% distinct(sequence) %>%
  mutate(model = "real", output = real) %>% select(-real)

d = d.test %>% select(-real)
然后将它们堆叠起来:

bind_rows(d, d.real)
如果排序很重要,请添加
%%>%arrange(sequence)



评论。OP中的问题源于不整洁的数据。如果你不知道我的意思,阅读可能会有帮助。

这就是你想要的吗

 x <- unique(
         melt(d.test,
              id.vars = c("sequence", "foo"),
              measure.vars = c("real"),
              variable.name = "model",
              value.name = "output" ))

d.test$real<-NULL

names(x) <- names(d.test)

rbind(d.test, x)

x另一种方法是:

temp = unique(d.test[,-c(3,4)])
temp$model = "real"
colnames(temp)[3] = "output"
d.test$real = NULL
d.test = rbind(d.test,temp)
这将返回:

> d.test
   sequence foo model output
1         1   3     a     12
2         1   3     b     29
3         1   3     c     10
4         1   3     d     38
5         1   3     e     10
6         2   3     a     38
7         2   3     b     10
8         2   3     c     29
9         2   3     d     56
10        2   3     e     10
11        1   3  real     12
61        2   3  real     15
编辑: 如果要避免对模型和输出的列索引进行harcoding,请执行以下操作:

temp = unique(d.test[,!grepl("(model|output)",colnames(d.test))])


dplyr的另一种可能解决方案:

 > library(dplyr)
    > 
    > 
    > d.real <- d.test %>% group_by(sequence) %>%
                 select(foo=unique(foo),output = unique(real))  %>% 
                 unique() %>% mutate(model='real') %>% as.data.frame() %>% rbind(d.test[,1:4]) 
                 %>% arrange(sequence,model)
    Adding missing grouping variables: `sequence` #ignore it
    > 
    > knitr::kable(d.real)


    | sequence| foo| output|model |
    |--------:|---:|------:|:-----|
    |        1|   3|     12|a     |
    |        1|   3|     29|b     |
    |        1|   3|     10|c     |
    |        1|   3|     38|d     |
    |        1|   3|     10|e     |
    |        1|   3|     12|real  |
    |        2|   3|     38|a     |
    |        2|   3|     10|b     |
    |        2|   3|     29|c     |
    |        2|   3|     56|d     |
    |        2|   3|     10|e     |
    |        2|   3|     15|real  |
>库(dplyr)
> 
> 
>d.实际百分比分组依据(顺序)%>%
选择(foo=unique(foo),output=unique(real))%>%
unique()%%>%mutate(model='real')%%>%as.data.frame()%%>%rbind(d.test[,1:4])
%>%排列(顺序、型号)
添加缺少的分组变量:`sequence`#忽略它
> 
>克尼特:卡布尔(d.real)
|序列| foo |输出|模型|
|--------:|---:|------:|:-----|
|1 | 3 | 12 | a|
|1 | 3 | 29 | b|
|1 | 3 | 10 | c|
|1 | 3 | 38 | d|
|1 | 3 | 10 | e|
|1 | 3 | 12 |真实|
|2 | 3 | 38 | a|
|2 | 3 | 10 | b|
|2 | 3 | 29 | c|
|2 | 3 | 56 | d|
|2 | 3 | 10 | e|
|2 | 3 | 15 |真实|

诀窍是加宽已经很长的数据,然后将其转换回长格式,确保在重塑中包含
real

library(dplyr)
library(tidyr)

d.test %>%
  spread(model, output) %>%
  gather(model, output, -sequence, -foo) %>%
  arrange(sequence, model)
#>    sequence foo model output
#> 1         1   3     a     12
#> 2         1   3     b     29
#> 3         1   3     c     10
#> 4         1   3     d     38
#> 5         1   3     e     10
#> 6         1   3  real     12
#> 7         2   3     a     38
#> 8         2   3     b     10
#> 9         2   3     c     29
#> 10        2   3     d     56
#> 11        2   3     e     10
#> 12        2   3  real     15
spread
是用于扩展长数据的tidyr函数。它获取一个数据帧、一列键的名称(变量名)和一列值的名称,并将键分散到几列上。这是将
模型
-
输出
对分散到多个列后的数据外观

# Convert to wide-format so there is one real per row
d.test.wide <- d.test %>%
  spread(model, output)
d.test.wide
#>   sequence foo real  a  b  c  d  e
#> 1        1   3   12 12 29 10 38 10
#> 2        2   3   15 38 10 29 56 10
#转换为宽格式,使每行有一个实数
d、 测试范围%
排列(模型、输出)
d、 测试范围
#>序列foo实a b c d e
#> 1        1   3   12 12 29 10 38 10
#> 2        2   3   15 38 10 29 56 10
gather
是熔化数据的tidyr函数。我们使用dplyr的列选择语法,告诉它收集除标识符
sequence
foo
之外的所有列,将键存储在
model
列中,并将值存储在
output
列中


我们还可以显式地选择要收集的列:
d.test.wide%>%gather(model、output、real、a:e)
。剩余的未选择列将用作标识符。

Fwiw,我认为重塑2及其熔化现在是dplyr等人的祖先,而不是近亲。我知道,我只是很难强迫自己使用“新”列:)不要认为你对
数据表
解决方案感兴趣,而是类似
DT[,list(model=c(model,“real”)、output=c(output,real[1])、by=sequence]
应该适合您的情况。(
DT
当然是
as.data.table(d.test)
)@nicola很有意思,谢谢。从未真正使用过
数据。表
,但有它作为参考是很好的。输出是我想要的,是的,但在问题中我已经描述过我尝试过。哦,d'Oh,刚刚意识到这是OP已经想到的。尽管如此,这似乎是正确的方法。这看起来比
reformae2/unique
解决方案,但如果可能的话,我不想手动指定所有其他列,如
foo
。谢谢!这确实有效,但它非常依赖于手动输入的列索引,而干净的解决方案只需指定您感兴趣的列名。我在问题中已经澄清了这一点。
# Convert to wide-format so there is one real per row
d.test.wide <- d.test %>%
  spread(model, output)
d.test.wide
#>   sequence foo real  a  b  c  d  e
#> 1        1   3   12 12 29 10 38 10
#> 2        2   3   15 38 10 29 56 10