非常规数据框架重塑

时间:2017-10-04 21:36:53

标签: r

我正在尝试从

重塑表格
col1| col2|col3|id
v1  | v2  | v3 |1
v2  | v1  | v3 |2

col1|col2|id
v1  | v2 | 1
v2  | v3 | 1
v2  | v1 | 2
v1  | v3 | 2

基本上为每个id创建以下列对。

很抱歉没有明确的标题,但不知道如何描述我正在尝试做的事情。

5 个答案:

答案 0 :(得分:4)

对于提交的案例:

library(dplyr)
bind_rows(
    select(df, -col3),
    select(df,  col1=col2, col2=col3, id)
)

了解更多列,假设id是最后一列:

library(dplyr)

NcolsToReduce <- ncol(df) - 2

lapply(1:NcolsToReduce, function(i){
  x <- select(df, i, i+1, id)
  names(x) <- c("col1", "col2", "id")
  x
  }) %>% bind_rows()

我觉得那很有用。

答案 1 :(得分:3)

下面的解决方案应该适用于任意数量的列id变量,它可以是任何列(而不仅仅是最后一列)。

它使用melt()从长到格式重新整形,shift()将下一行作为列对的第二列:

library(data.table)
melt(setDT(df), id.vars = "id")[
  , .(col1 = head(value, -1L), col2 = head(shift(value, 1L, type = "lead"), -1L)), by = id]
    id col1 col2
1:  1   v1   v2
2:  1   v2   v3
3:  2   v2   v1
4:  2   v1   v3

数据

library(data.table)
df <- fread(
  "col3| col2|col1|id
v1  | v2  | v3 |1
v2  | v1  | v3 |2",
  sep = "|")

答案 2 :(得分:1)

library(zoo)
library(tidyr)
library(stringr)
Dat$New=apply(Dat[,1:3],1,function(x) toString(rollapply(x, 2, FUN=function(z) paste(z,collapse =';'))))
NewDat=Dat[,c('id','New')]
NewDat=NewDat%>%
    transform(New = strsplit(New, ",")) %>%
    unnest(New)

NewDat[,c('col1','col2')]=str_split_fixed(NewDat$New,';',2)

NewDat
  id    New col1 col2
1  1  v1;v2   v1   v2
2  1  v2;v3   v2   v3
3  2  v2;v1   v2   v1
4  2  v1;v3   v1   v3

答案 3 :(得分:1)

来自dplyrtidyr的解决方案。我们的想法是首先将数据从宽格式转换为长格式。之后,复制每个id组中间的行,更改列号,然后将其转换回宽格式。

# Load packages
library(dplyr)
library(tidyr)

# Create example data frame
dt <- data_frame(col1 = c("v1", "v2"),
                 col2 = c("v2", "v1"),
                 col3 = c("v3", "v3"),
                 id = c(1L, 2L))


# Process the data
dt2 <- dt %>%
  gather(Cols, Value, -id) %>%
  arrange(id) %>%
  group_by(id) %>%
  slice(c(1, 2, 2, 3)) %>%
  mutate(Cols = paste0("col", rep(1:2, each = 2))) %>%
  mutate(id2 = rep(1:2, 2)) %>%
  spread(Cols, Value) %>%
  select(col1, col2, id)

# View the result
dt2
# A tibble: 4 x 3
# Groups:   id [2]
   col1  col2    id
* <chr> <chr> <int>
1    v1    v2     1
2    v2    v3     1
3    v2    v1     2
4    v1    v3     2

答案 4 :(得分:0)

data.table解决方案,假设id列是最后一列。

library(data.table)
setDT(df)

rbindlist(lapply(1:(ncol(df)-2), function(x) df[, c(x,x+1,ncol(df)), with = FALSE]))[order(id)]

#    col1 col2 id
# 1:   v1   v2  1
# 2:   v2   v3  1
# 3:   v2   v1  2
# 4:   v1   v3  2

等效使用基数相似,但有点混乱,可能效率较低。

#setDF(df)
df2 <- do.call("rbind", lapply(1:(ncol(df)-2), function(x) setNames(df[, c(x,x+1,ncol(df))], names(df)[c(1,2,ncol(df))])))
df2[order(df2[,3]),]