我需要将宽表重塑为长格式,但为每条记录保留多个字段,例如:

  • 本文关键字:记录 保留 例如 字段 格式 r
  • 更新时间 :
  • 英文 :

src   hop1   hop2   hop3    hop4    destination
 A     B      C      NA      NA      NA
 P     Q      R      S       NA      NA
 H     I      J      K       L       M

现在我想将此表融化为以下格式

src nn en
 A  B  C
 B  C  C
 P  Q  S
 Q  R  S
 R  S  S
 H  I  M
 I  J  M
 J  K  M
 K  L  M
 L  M  M

我对熔化和重塑有基本的了解,但无法想象如何利用这些功能来实现所需的输出。

您基本上希望收集所有列,按每行分组。然后期待前导值和最后一个值。所以在 dplyr 中是这样的东西:

dat %>%
  mutate(row=row_number()) %>%
  gather(key, src, -row) %>%
  drop_na() %>%
  group_by(row) %>%
  mutate(nn=lead(src), en=last(src)) %>%
  ungroup() %>%
  filter(!is.na(nn)) %>%
  arrange(row) %>%
  select(src, nn, en)
## A tibble: 10 x 3
#   src   nn    en   
#   <chr> <chr> <chr>
# 1 A     B     C    
# 2 B     C     C    
# 3 P     Q     S    
# 4 Q     R     S    
# 5 R     S     S    
# 6 H     I     M    
# 7 I     J     M    
# 8 J     K     M    
# 9 K     L     M    
#10 L     M     M 

或者在基础 R 中像这样:

tmp <- na.omit(data.frame(row=seq_len(nrow(dat)), src=unlist(dat), stringsAsFactors=FALSE))
tmp$nn <- ave(tmp$src, tmp$row, FUN=function(x) c(tail(x,-1),NA) )
tmp$en <- ave(tmp$src, tmp$row, FUN=function(x) tail(x,1) )
tmp <- tmp[!is.na(tmp$nn),]
tmp[order(tmp$row), c("src","nn","en")]
#      src nn en
#src1    A  B  C
#hop11   B  C  C
#src2    P  Q  S
#hop12   Q  R  S
#hop22   R  S  S
#src3    H  I  M
#hop13   I  J  M
#hop23   J  K  M
#hop33   K  L  M
#hop43   L  M  M

dat在哪里:

dat <- read.table(text="src   hop1   hop2   hop3    hop4    destination
 A     B      C      NA      NA      NA
 P     Q      R      S       NA      NA
 H     I      J      K       L       M", header=TRUE, stringsAsFactors=FALSE)
或者

我们可以使用 base R 中的apply

out <- do.call(rbind, apply(dat, 1, function(x) {
    x1 <- na.omit(x)
    data.frame(src = x1[-length(x1)], nn = x1[-1], en = x1[length(x1)])
   }))
row.names(out) <- NULL
out
#   src nn en
#1    A  B  C
#2    B  C  C
#3    P  Q  S
#4    Q  R  S
#5    R  S  S
#6    H  I  M
#7    I  J  M
#8    J  K  M
#9    K  L  M
#10   L  M  M

或者base R的另一个选项是使用 max.col 查找最后一个非 NA 元素,使用 rep 复制每行中的最后一个非 NA 元素并创建data.frame

ij <- cbind(seq_len(nrow(dat)), max.col(!is.na(dat), "last"))
v1 <- dat[ij]
i1 <- rowSums(!is.na(dat))
src <- na.omit(c(t(replace(dat, ij, NA))))
nn <-  na.omit(c(t(dat)[-1,])) 
data.frame(src ,nn,  en = rep(v1, i1-1 ))
#   src nn en
#1    A  B  C
#2    B  C  C
#3    P  Q  S
#4    Q  R  S
#5    R  S  S
#6    H  I  M
#7    I  J  M
#8    J  K  M
#9    K  L  M
#10   L  M  M

最新更新