Мне нужно преобразовать мою широкую таблицу в длинный формат, но сохранить несколько полей для каждой записи, например: - PullRequest
0 голосов
/ 30 апреля 2019
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

У меня есть базовые представления о плавлении и изменении формы, но я не могу представить, как я могу использовать эти функции для получения желаемого результата.

Ответы [ 2 ]

2 голосов
/ 30 апреля 2019

По сути, вы хотите собрать все столбцы, сгруппированные по каждой строке.Затем с нетерпением ждем ведущего значения и последнего значения.Так что-то вроде этого в 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)
1 голос
/ 30 апреля 2019

Или мы можем использовать apply из base R

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...