Изменение формы data.frame из широкого в длинный формат
83833 просмотра
6 ответа
У меня возникли проблемы с преобразованием моего data.frame
из широкого стола в длинный стол. На данный момент это выглядит так:
Code Country 1950 1951 1952 1953 1954
AFG Afghanistan 20,249 21,352 22,532 23,557 24,555
ALB Albania 8,097 8,986 10,058 11,123 12,246
Теперь я хотел бы превратить это data.frame
в длинный data.frame
. Что-то вроде этого:
Code Country Year Value
AFG Afghanistan 1950 20,249
AFG Afghanistan 1951 21,352
AFG Afghanistan 1952 22,532
AFG Afghanistan 1953 23,557
AFG Afghanistan 1954 24,555
ALB Albania 1950 8,097
ALB Albania 1951 8,986
ALB Albania 1952 10,058
ALB Albania 1953 11,123
ALB Albania 1954 12,246
Я смотрел и уже попытался с помощью melt()
и reshape()
функции , как некоторые люди предлагали в подобных вопросах. Однако пока я получаю только грязные результаты.
Если это возможно, я хотел бы сделать это с помощью reshape()
функции, поскольку она выглядит немного приятнее в обращении.
Ответы (6)
72 плюса
reshape()
требует времени, чтобы привыкнуть, так же как melt
/ cast
. Вот решение с изменением формы, если предположить, что ваш фрейм данных называется d
:
reshape(d, direction = "long", varying = list(names(d)[3:7]), v.names = "Value",
idvar = c("Code","Country"), timevar = "Year", times = 1950:1954)
Автор: Aniko
Размещён: 02.02.2010 04:07
114 плюса
Три альтернативных решения:
1: с reshape2
library(reshape2)
long <- melt(wide, id.vars = c("Code", "Country"))
давая:
Code Country variable value
1 AFG Afghanistan 1950 20,249
2 ALB Albania 1950 8,097
3 AFG Afghanistan 1951 21,352
4 ALB Albania 1951 8,986
5 AFG Afghanistan 1952 22,532
6 ALB Albania 1952 10,058
7 AFG Afghanistan 1953 23,557
8 ALB Albania 1953 11,123
9 AFG Afghanistan 1954 24,555
10 ALB Albania 1954 12,246
Некоторые альтернативные обозначения, которые дают тот же результат:
# you can also define the id-variables by column number
melt(wide, id.vars = 1:2)
# as an alternative you can also specify the measure-variables
# all other variables will then be used as id-variables
melt(wide, measure.vars = 3:7)
melt(wide, measure.vars = as.character(1950:1954))
2: с data.table
Вы можете использовать ту же melt
функцию, что и в reshape2
пакете (это расширенная и улучшенная реализация). melt
from data.table
также имеет больше параметров, чем melt
-function из reshape2
. Например, вы также можете указать имя переменной-столбца:
library(data.table)
long <- melt(setDT(wide), id.vars = c("Code","Country"), variable.name = "year")
Некоторые альтернативные обозначения:
melt(setDT(wide), id.vars = 1:2, variable.name = "year")
melt(setDT(wide), measure.vars = 3:7, variable.name = "year")
melt(setDT(wide), measure.vars = as.character(1950:1954), variable.name = "year")
3: с tidyr
library(tidyr)
long <- wide %>% gather(year, value, -c(Code, Country))
Некоторые альтернативные обозначения:
wide %>% gather(year, value, -Code, -Country)
wide %>% gather(year, value, -1:-2)
wide %>% gather(year, value, -(1:2))
wide %>% gather(year, value, -1, -2)
wide %>% gather(year, value, 3:7)
wide %>% gather(year, value, `1950`:`1954`)
Если вы хотите исключить NA
значения, вы можете добавить na.rm = TRUE
к melt
, а также gather
функции.
Другая проблема с данными состоит в том, что значения будут считываться R как символьные значения (как результат ,
чисел). Вы можете исправить это с помощью gsub
и as.numeric
:
long$value <- as.numeric(gsub(",", "", long$value))
Или непосредственно с data.table
или dplyr
:
# data.table
long <- melt(setDT(wide),
id.vars = c("Code","Country"),
variable.name = "year")[, value := as.numeric(gsub(",", "", value))]
# tidyr and dplyr
long <- wide %>% gather(year, value, -c(Code,Country)) %>%
mutate(value = as.numeric(gsub(",", "", value)))
Данные:
wide <- read.table(text="Code Country 1950 1951 1952 1953 1954
AFG Afghanistan 20,249 21,352 22,532 23,557 24,555
ALB Albania 8,097 8,986 10,058 11,123 12,246", header=TRUE, check.names=FALSE)
Автор: Jaap
Размещён: 15.09.2014 08:09
32 плюса
Используя пакет изменения формы :
#data
x <- read.table(textConnection(
"Code Country 1950 1951 1952 1953 1954
AFG Afghanistan 20,249 21,352 22,532 23,557 24,555
ALB Albania 8,097 8,986 10,058 11,123 12,246"), header=TRUE)
library(reshape)
x2 <- melt(x, id = c("Code", "Country"), variable_name = "Year")
x2[,"Year"] <- as.numeric(gsub("X", "" , x2[,"Year"]))
Автор: Shane
Размещён: 02.02.2010 04:08
11 плюса
Так как этот ответ помечается г-FAQ , я чувствовал , что это было бы полезно разделить другую альтернативу от базовой R: stack
.
Заметьте, однако, что stack
это не работает с factor
s - это работает, только если is.vector
есть TRUE
, и из документации для is.vector
мы находим, что:
is.vector
возвращает,TRUE
если x является вектором указанного режима, не имеющим никаких атрибутов, кроме имен . ВозвращаетсяFALSE
иначе.
Я использую пример данных из ответа @ Jaap , где значения в столбцах года factor
s.
Вот stack
подход:
cbind(wide[1:2], stack(lapply(wide[-c(1, 2)], as.character)))
## Code Country values ind
## 1 AFG Afghanistan 20,249 1950
## 2 ALB Albania 8,097 1950
## 3 AFG Afghanistan 21,352 1951
## 4 ALB Albania 8,986 1951
## 5 AFG Afghanistan 22,532 1952
## 6 ALB Albania 10,058 1952
## 7 AFG Afghanistan 23,557 1953
## 8 ALB Albania 11,123 1953
## 9 AFG Afghanistan 24,555 1954
## 10 ALB Albania 12,246 1954
Автор: A5C1D2H2I1M1N2O1R2T1
Размещён: 09.01.2018 05:31
9 плюса
Вот еще один пример, показывающий использование gather
from tidyr
. Вы можете выбрать столбцы gather
либо, удалив их по отдельности (как я здесь), либо указав нужные вам годы.
Обратите внимание, что для обработки запятых (и X добавляется, если check.names = FALSE
не установлено), я также использую dplyr
mutate с parse_number
from readr
для преобразования текстовых значений обратно в числа. Все они являются частью tidyverse
и поэтому могут быть загружены вместе сlibrary(tidyverse)
wide %>%
gather(Year, Value, -Code, -Country) %>%
mutate(Year = parse_number(Year)
, Value = parse_number(Value))
Возвращает:
Code Country Year Value
1 AFG Afghanistan 1950 20249
2 ALB Albania 1950 8097
3 AFG Afghanistan 1951 21352
4 ALB Albania 1951 8986
5 AFG Afghanistan 1952 22532
6 ALB Albania 1952 10058
7 AFG Afghanistan 1953 23557
8 ALB Albania 1953 11123
9 AFG Afghanistan 1954 24555
10 ALB Albania 1954 12246
Автор: Mark Peterson
Размещён: 04.12.2016 07:20
2 плюса
Вот решение sqldf :
sqldf("Select Code, Country, '1950' As Year, `1950` As Value From wide
Union All
Select Code, Country, '1951' As Year, `1951` As Value From wide
Union All
Select Code, Country, '1952' As Year, `1952` As Value From wide
Union All
Select Code, Country, '1953' As Year, `1953` As Value From wide
Union All
Select Code, Country, '1954' As Year, `1954` As Value From wide;")
Чтобы сделать запрос без ввода всего, вы можете использовать следующее:
Спасибо Г. Гротендику за его реализацию.
ValCol <- tail(names(wide), -2)
s <- sprintf("Select Code, Country, '%s' As Year, `%s` As Value from wide", ValCol, ValCol)
mquery <- paste(s, collapse = "\n Union All\n")
cat(mquery) #just to show the query
# Select Code, Country, '1950' As Year, `1950` As Value from wide
# Union All
# Select Code, Country, '1951' As Year, `1951` As Value from wide
# Union All
# Select Code, Country, '1952' As Year, `1952` As Value from wide
# Union All
# Select Code, Country, '1953' As Year, `1953` As Value from wide
# Union All
# Select Code, Country, '1954' As Year, `1954` As Value from wide
sqldf(mquery)
# Code Country Year Value
# 1 AFG Afghanistan 1950 20,249
# 2 ALB Albania 1950 8,097
# 3 AFG Afghanistan 1951 21,352
# 4 ALB Albania 1951 8,986
# 5 AFG Afghanistan 1952 22,532
# 6 ALB Albania 1952 10,058
# 7 AFG Afghanistan 1953 23,557
# 8 ALB Albania 1953 11,123
# 9 AFG Afghanistan 1954 24,555
# 10 ALB Albania 1954 12,246
К сожалению, я так не думаю PIVOT
и UNPIVOT
сработаю R
SQLite
. Если вы хотите написать свой запрос более сложным образом, вы также можете взглянуть на эти сообщения:
Использование sprintf
написания SQL-запросов или передачи переменных вsqldf
Вопросы из категории :
- r Как получить доступ к последнему значению в векторе?
- r Пакеты оптимизации для R
- r Есть ли у R такие операторские операции, как Perl qw ()?
- r Библиотека / инструмент для рисования тройных / треугольных графиков
- r Участки без заголовков / надписей в R
- dataframe Разница между скобками [] и двойной скобкой [[]] для доступа к элементам списка или кадра данных
- dataframe Уровни коэффициента отбрасывания в заданном кадре данных
- dataframe Как отсортировать фрейм данных по нескольким столбцам
- dataframe Как объединить (объединить) кадры данных (внутренний, внешний, левый, правый)?
- reshape How do I resize a matrix in MATLAB?
- reshape Преобразование данных из многих строк во многие столбцы
- reshape Изменение формы data.frame из широкого в длинный формат
- reshape Измените 3d матрицу на 2d матрицу
- reshape Как изменить данные из длинного в широкий формат
- r-faq Расчет скользящей средней
- r-faq Проверить, содержит ли вектор данный элемент
- r-faq Поиск всех позиций для нескольких элементов в векторе