#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. Данные примера являются частью фактических данных. Единственные изменения, которые мне пришлось внести в код, касались имени набора данных и заголовков столбцов.