Я хочу повернуть столбец result
в df
по горизонтали, создав набор данных с отдельной строкой для каждой комбинации region
, state
, county
, где столбцы упорядочены по year
, а затем по city
.
Я также хочу идентифицировать каждую строку в новом наборе данных с помощью region
, state
и county
и удалить пробел между четырьмя столбцами results
. Приведенный ниже код делает все это, но я подозреваю, что он не очень эффективен.
Есть ли способ сделать это с помощью reshape2
без создания уникального идентификатора для каждой группы и нумерации наблюдений внутри каждой группы? Есть ли способ использовать apply вместо цикла for для удаления пробелов из матрицы? (Здесь матрица используется иначе, чем математическая или программная конструкция.) Я понимаю, что это два отдельных вопроса, и, возможно, мне следует публиковать каждый вопрос отдельно.
Учитывая, что я могу добиться желаемого результата и хочу только улучшить код, я не знаю, стоит ли мне вообще публиковать это, но я надеюсь научиться. Спасибо за любой совет.
df <- read.table(text= "
region state county city year result
1 1 1 1 1 1
1 1 1 2 1 2
1 1 1 1 2 3
1 1 1 2 2 4
1 1 2 3 1 4
1 1 2 4 1 3
1 1 2 3 2 2
1 1 2 4 2 1
1 2 1 1 1 0
1 2 1 2 1 NA
1 2 1 1 2 0
1 2 1 2 2 0
1 2 2 3 1 2
1 2 2 4 1 2
1 2 2 3 2 2
1 2 2 4 2 2
2 1 1 1 1 9
2 1 1 2 1 9
2 1 1 1 2 8
2 1 1 2 2 8
2 1 2 3 1 1
2 1 2 4 1 0
2 1 2 3 2 1
2 1 2 4 2 0
2 2 1 1 1 2
2 2 1 2 1 4
2 2 1 1 2 6
2 2 1 2 2 8
2 2 2 3 1 3
2 2 2 4 1 3
2 2 2 3 2 2
2 2 2 4 2 2
", header=TRUE, na.strings=NA)
desired.result <- read.table(text= "
region state county results
1 1 1 1234
1 1 2 4321
1 2 1 0.00
1 2 2 2222
2 1 1 9988
2 1 2 1010
2 2 1 2468
2 2 2 3322
", header=TRUE, colClasses=c('numeric','numeric','numeric','character'))
# redefine variables for package reshape2 creating a unique id for each
# region, state, county combination and then number observations in
# each of those combinations
library(reshape2)
id.var <- df$region*100000 + df$state*1000 + df$county
obsnum <- sequence(rle(id.var)$lengths)
df2 <- dcast(df, region + state + county ~ obsnum, value.var = "result")
# remove spaces between columns of results matrix
# with a for-loop. How can I use apply to do this?
x <- df2[,4:(4+max(obsnum)-1)]
# use a dot to represent a missing observation
x[is.na(x)] = '.'
x.cat = numeric(nrow(x))
for(i in 1:nrow(x)) {
x.cat[i] = paste(x[i,], collapse="")
}
df3 <- cbind(df2[,1:3],x.cat)
colnames(df3) <- c("region", "state", "county", "results")
df3
df3 == desired.result
РЕДАКТИРОВАТЬ:
Ответ Мэтью Лундберга ниже превосходен. Впоследствии я понял, что мне также необходимо создать набор выходных данных, в котором четыре столбца результатов выше содержат числовые, рациональные числа и разделены пробелом. Итак, я опубликовал очевидный способ сделать это ниже, который изменяет ответ Мэтью. Я не знаю, является ли это принятым протоколом, но новый сценарий кажется настолько непосредственно связанным с исходным сообщением, что я не подумал, что должен публиковать новый вопрос.