将数据从长格式更改为宽格式

时间:2019-05-30 02:33:46

标签: r dplyr reshape

我正在寻找一种从长格式到宽格式重塑数据的快速方法。现在,我已经尝试了使用嵌套嵌套循环的代码,尽管工作已经完成,但是生成输出仍需要很长时间。

SN NN EE Service_tier
A  B  C  economy
B  C  C  economy
P  Q  R  regular
Q  S  R  regular
S  R  R  regular
H  I  L  economy
I  J  L  economy
J  K  L  economy
K  L  L  economy

预期输出如下

SN hop1 hop2 hop3 hop4 service_tier
A   B    C              economy
P   Q    S    R         regular
H   I    J    K    L    economy

目前,以下代码可以完成工作。确保有一种有效且干净的方法来做到这一点。

for (i in 1:lasrow){
  sn <- raw_d[i,1]
  nn <- raw_d[i,2]
  en <- raw_d[i,3]

  lc <- 1

  if(nn == en){
    d[lr,lc]<-sn
    d[lr,lc+1]<-nn
    d[lr,lc+2]<-en
    lr <- lr+1
  }
  else{
    while(nn!=en){
      d[lr,lc]<-sn
      lc <- lc+1
      next_d <- filter(raw_d,raw_d$SN==sn,raw_d$EN==en)
      if(dim(next_d)[1]==0){
        d[lr,lc]<-"broken bf"
        lc <- lc+1
        break
      }else{
        sn <- next_d$NN
        nn <- next_d$NN
        }
      }
    d[lr,lc]<-en
    lr<-lr+1
  }
}

3 个答案:

答案 0 :(得分:0)

一个选择是使用rleid中的data.tablegather将数据帧转换为长格式,从每个组中删除重复项,分配列名和{{1} }恢复为宽格式。

spread

答案 1 :(得分:0)

我们可以使用data.table。将'data.frame'转换为'dat.table'(setDT(df1),在'Service_tier'上按rleid分组,将'SN'的值更改为first元素,按' grp”,然后按“ Service_tier”,“ SN”分组,获得Data.table子集的unique元素和dcast从'long'到'wide'格式

library(data.table)
dcast(setDT(df1)[, SN := first(SN), rleid(Service_tier)][, 
    unique(unlist(.SD)), .(SN, Service_tier)], 
    SN + Service_tier ~ paste0("hop", rowid(SN)), value.var = "V1", fill = "")
#  SN Service_tier hop1 hop2 hop3 hop4
#1:  A      economy    B    C          
#2:  H      economy    I    J    K    L
#3:  P      regular    Q    S    R     

数据

df1 <- structure(list(SN = c("A", "B", "P", "Q", "S", "H", "I", "J", 
"K"), NN = c("B", "C", "Q", "S", "R", "I", "J", "K", "L"), EE = c("C", 
"C", "R", "R", "R", "L", "L", "L", "L"), Service_tier = c("economy", 
"economy", "regular", "regular", "regular", "economy", "economy", 
"economy", "economy")), class = "data.frame", row.names = c(NA, 
-9L))

答案 2 :(得分:0)

此处的关键点是确定哪些行属于哪个组。假设rleid(Service_tier)中的更改表示新组的开始,则Ronakakrun的答案都使用Service_tier

这可能是示例数据集所建议的,但不能认为是保证的。恕我直言,Service_tier只是一个属性而不是一个键。实际上,OP正在测试其代码段中的NN == EE,以切换到新的组。

在下面的data.table解决方案中,分组由cumsum(shift(NN == EE, fill = TRUE))确定,它测试NNEE的相等性,将结果滞后到下一行开始的下一行,并通过使用TRUE计数cumsum()来枚举组。

在简化版本(不进行重塑)中,跳由toString()函数聚合:

library(data.table)
setDT(d)[, .(SN = first(SN), hops = toString(NN), Service_tier = first(Service_tier)), 
  by = .(grp = cumsum(shift(NN == EE, fill = TRUE)))][]
   grp SN       hops Service_tier
1:   1  A       B, C      economy
2:   2  P    Q, S, R      regular
3:   3  H I, J, K, L      economy

要从长格式转换为宽格式,请使用dcast()

library(data.table)
library(magrittr)   # piping used to improve readability
w <- setDT(d)[, .(SN = first(SN), hops = NN, Service_tier = first(Service_tier)), 
  by = .(grp = cumsum(shift(NN == EE, fill = TRUE)))] %>% 
  dcast(grp + ... ~ rowid(grp, prefix = "hop"), value.var = "hops", fill = "")  %>%  
  setcolorder(c(1:2, 4:ncol(w), 3))

w
   grp SN hop1 hop2 hop3 hop4 Service_tier
1:   1  A    B    C                economy
2:   2  P    Q    S    R           regular
3:   3  H    I    J    K    L      economy

setcolorder()用于按OP期望的顺序重新排列列。这是在原位完成的,即无需复制整个数据对象。

数据

library(data.table)

d <- fread("SN NN EE Service_tier
A  B  C  economy
B  C  C  economy
P  Q  R  regular
Q  S  R  regular
S  R  R  regular
H  I  L  economy
I  J  L  economy
J  K  L  economy
K  L  L  economy")