R — Транспонирование частей фрейма данных

#r #reshape #transpose #reorganize

#r #изменение формы #транспонирование #реорганизация

Вопрос:

У меня есть файл .dbf, который я экспортировал из ArcGIS 10.1, и мне нужно его реорганизовать. Примером данных является:

        V1               V2
40.000000000000000 41.000000000000000

40.000000000000000 42.000000000000000

41.000000000000000 40.000000000000000

41.000000000000000 42.000000000000000

41.000000000000000 43.000000000000000

42.000000000000000 40.000000000000000

42.000000000000000 41.000000000000000

42.000000000000000 43.000000000000000

43.000000000000000 41.000000000000000

43.000000000000000 42.000000000000000
  

Мне нужны данные в формате, в котором для каждого уникального значения в первом столбце есть только одна строка, при этом все соответствующие значения из второго столбца теперь отображаются в этой строке, например:

   V1                   V2              V3                  V4
40.000000000000000 41.000000000000000 42.000000000000000

41.000000000000000 40.000000000000000 42.000000000000000 43.000000000000000

42.000000000000000 40.000000000000000 41.000000000000000 43.000000000000000

43.000000000000000 41.000000000000000 42.000000000000000
  

Если кто-нибудь может помочь мне с этой проблемой, я был бы признателен. Спасибо!

Ответ №1:

Вы можете разделить свой фрейм данных, используя split функцию в первом столбце и use lapply для извлечения ваших векторов:

 dat = data.frame(X1=c(40, 40, 41, 41, 41, 42, 42, 42, 43, 43),
                 X2=c(41, 42, 40, 42, 43, 40, 41, 43, 41, 42))
res <- lapply(split(dat, dat[,1]), function(d) c(d[1,1], sort(unique(d[,2]))))
res
# $`40`
# [1] 40 41 42
# 
# $`41`
# [1] 41 40 42 43
# 
# $`42`
# [1] 42 40 41 43
# 
# $`43`
# [1] 43 41 42
  

Большинство, вероятно, предпочло бы сохранить данные в этом формате, но вы также можете объединить список в матрицу, заполнив векторы NA значениями:

 max.len <- max(unlist(lapply(res, length)))
do.call(rbind, lapply(res, function(x) { length(x) <- max.len ; x }))
#    [,1] [,2] [,3] [,4]
# 40   40   41   42   NA
# 41   41   40   42   43
# 42   42   40   41   43
# 43   43   41   42   NA
  

Комментарии:

1. 1, хорошая демонстрация NA заполнения для равной длины строк

Ответ №2:

Вы также можете сделать это в dplyr

 library(dplyr)
library(tidyr)
  dat%>% 
  group_by(X1) %>%
  mutate(Time=seq_along(X1)) 
  %>%spread(Time,X2)
 #Source: local data frame [4 x 4]

 #X1  1  2  3
#1 40 41 42 NA
#2 41 40 42 43
#3 42 40 41 43
#4 43 41 42 NA
  

Ответ №3:

По сути, это reshape проблема, но у вас нет переменной «time».

Вы можете легко создать переменную «time» следующим образом:

 dat$time <- with(dat, ave(X1, X1, FUN = seq_along))
  

Оттуда используйте reshape из базы R…

 reshape(dat, direction = "wide", idvar="X1", timevar="time")
#   X1 X2.1 X2.2 X2.3
# 1 40   41   42   NA
# 3 41   40   42   43
# 6 42   40   41   43
# 9 43   41   42   NA
  

… или dcast из «reshape2″…

 library(reshape2)
dcast(dat, X1 ~ time, value.var="X2")
#   X1  1  2  3
# 1 40 41 42 NA
# 2 41 40 42 43
# 3 42 40 41 43
# 4 43 41 42 NA
  

Комментарии:

1. Оба ваших предложения привели меня почти к цели. При использовании изменения формы данные были переформатированы правильно, но они сохранялись только один раз. Я получил следующее предупреждающее сообщение: Предупреждающее сообщение: в изменении формы (данные, idvar = idvar, timevar = timevar, variating = variating, : совпадение нескольких строк для time = 1: взято первым

2. Используя reshape2, я получил это сообщение об ошибке: ошибка в уникальном. значение по умолчанию(x) : unique() применяется только к векторам. Оба моих столбца возвращаются как TRUE, когда используется is.vector()

3. @user3769213, насколько ваши фактические данные похожи на этот пример данных, которыми вы поделились? Этот подход должен работать, если вы можете сгенерировать переменную «time» на основе вашей группировки или переменной «id».

4. Данные примера являются частью фактических данных. Единственные изменения, которые мне пришлось внести в код, касались имени набора данных и заголовков столбцов.