我正在尝试从
重塑表格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创建以下列对。
很抱歉没有明确的标题,但不知道如何描述我正在尝试做的事情。
答案 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)
来自dplyr
和tidyr
的解决方案。我们的想法是首先将数据从宽格式转换为长格式。之后,复制每个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]),]