R 非常规数据帧整形

R 非常规数据帧整形,r,R,我正试图改变桌子的形状 col1| col2|col3|id v1 | v2 | v3 |1 v2 | v1 | v3 |2 到 基本上为每个id创建一对以下列 抱歉,标题不清楚,但不确定如何描述我正在尝试做的事情。对于所介绍的案例: library(dplyr) bind_rows( select(df, -col3), select(df, col1=col2, col2=col3, id) ) 对于更多列,假设id是最后一列: library(dplyr)

我正试图改变桌子的形状

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

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


抱歉,标题不清楚,但不确定如何描述我正在尝试做的事情。

对于所介绍的案例:

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()
我想那会管用的

来自dplyr和tidyr的解决方案。其思想是首先将数据从宽格式转换为长格式。之后,复制每个ID组中间的行,更改列号,然后将其转换为宽格式。

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
# 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
假设id列是最后一列,则为data.table解决方案

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
使用base的等效方法类似,但有点混乱,可能效率更低

#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]),]

下面的解决方案应该适用于任意数量的列和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]
数据
看起来不错。如果有更多的栏目呢?有没有一种基于ncol的自动化方法?嗯。。。。。一个id列,还有更多的列,你想把它们重塑成2列加上id?一个较短的版本:meltsetdf,id=id[,.col1=headvalue,-1L,col2=tailvalue,-1L,by=id]
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 = "|")