长到宽:在R中将一列变为两列而不用于循环

时间:2014-12-19 14:26:04

标签: r reshape

我有一个名为Var的列的数据框,如下所示:

Var   Value
a     1.5
b     2.5
c     3
Red   4
Green 4.5 
Blue  0.5

我希望它看起来像这样:

Color Var   Value
Red   a     1.5
Red   b     2.5
Red   c     3
Red   Red   4
Green a     1.5
Green b     2.5
Green c     3
Green Green 4.5
Blue  a     1.5
Blue  b     2.5
Blue  c     3
Blue  Blue  0.5

换句话说,我想为Var的每个颜色值重复Var的所有非颜色值。有没有一种快速而巧妙的方法来避免循环?

3 个答案:

答案 0 :(得分:2)

类似于@RomanLuštrik的解决方案,但稍微容易一些(在我看来):

df <- read.table(text='Var   Value
a     1.5
b     2.5
c     3
Red   4
Green 4.5 
Blue  0.5', header=TRUE)

cols <- c('Red', 'Green', 'Blue')

do.call(rbind, lapply(cols, function(col, df){
  df[, 'Color'] <- col
  df[!(df$Var %in% cols) | df$Var == col,]
}, df=df))[, c('Color', 'Var', 'Value')]
##    Color   Var Value
## 1    Red     a   1.5
## 2    Red     b   2.5
## 3    Red     c   3.0
## 4    Red   Red   4.0
## 11 Green     a   1.5
## 21 Green     b   2.5
## 31 Green     c   3.0
## 5  Green Green   4.5
## 12  Blue     a   1.5
## 22  Blue     b   2.5
## 32  Blue     c   3.0
## 6   Blue  Blue   0.5

答案 1 :(得分:2)

这是一种略有不同的方法。它主要涉及创建两个list,然后我们可以与mapply“绑定”。

library(data.table) ## for rbindlist -- fast simple syntax

cols <- c('Red', 'Green', 'Blue')
CR <- df[df$Var %in% cols, ]   ## Color rows...
CR <- split(CR, 1:nrow(CR))    ## ... split into a list
## The other rows, replicated into a list
OR <- replicate(length(CR), df[!df$Var %in% cols, ], FALSE)

bindFun <- function(x, y) cbind(Color = y[[1]][1], rbind(x, y))

rbindlist(mapply(bindFun, OR, CR, SIMPLIFY = FALSE))
#     Color   Var Value
#  1:   Red     a   1.5
#  2:   Red     b   2.5
#  3:   Red     c   3.0
#  4:   Red   Red   4.0
#  5: Green     a   1.5
#  6: Green     b   2.5
#  7: Green     c   3.0
#  8: Green Green   4.5
#  9:  Blue     a   1.5
# 10:  Blue     b   2.5
# 11:  Blue     c   3.0
# 12:  Blue  Blue   0.5

答案 2 :(得分:1)

这对我有用。我创建了一个颜色矢量,并通过将非颜色行附加到一种特定颜色来为每种颜色创建一个data.frame。

xy <- read.table(text = "Var   Value
a     1.5
b     2.5
c     3
Red   4
Green 4.5 
Blue  0.5", header = TRUE)

cols <- c("Red", "Green", "Blue")

do.call("rbind", 
        sapply(cols, function(x, cols, xy) {
          nocols <- xy[!xy$Var %in% cols, ]
          rbind(nocols, xy[xy$Var %in% x, ])
        }, cols = cols, xy = xy, simplify = FALSE)
        )

          Var Value
Red.1       a   1.5
Red.2       b   2.5
Red.3       c   3.0
Red.4     Red   4.0
Green.1     a   1.5
Green.2     b   2.5
Green.3     c   3.0
Green.5 Green   4.5
Blue.1      a   1.5
Blue.2      b   2.5
Blue.3      c   3.0
Blue.6   Blue   0.5