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 = "|")