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()
조금 더 좋기 때문에 함수 로 수행하고 싶습니다 .
답변
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)
답변
세 가지 대안 솔루션 :
1) data.table:
패키지 melt
에서 와 동일한 기능을 사용할 수 있습니다 reshape2
(확장 및 개선 된 구현). melt
from data.table
에는 또한 melt
-function from 보다 많은 매개 변수가 있습니다 reshape2
. 예를 들어 변수 열의 이름을 지정할 수도 있습니다.
library(data.table)
long <- melt(setDT(wide), id.vars = c("Code","Country"), variable.name = "year")
이것은 다음을 제공합니다.
> long 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
대체 표기법 :
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")
2) 깔끔한:
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`)
3) 개편 2:
library(reshape2)
long <- melt(wide, id.vars = c("Code", "Country"))
동일한 결과를 제공하는 몇 가지 대체 표기법 :
# 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은퇴했습니다. CRAN을 유지하는 데 필요한 변경 만 수행됩니다. ( 소스 )
- 제외 할 경우
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)
답변
사용하여 모양 변경 패키지를 :
#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"]))
답변
으로 tidyr_1.0.0
, 또 다른 옵션은pivot_longer
library(tidyr)
pivot_longer(df1, -c(Code, Country), values_to = "Value", names_to = "Year")
# A tibble: 10 x 4
# Code Country Year Value
# <fct> <fct> <chr> <fct>
# 1 AFG Afghanistan 1950 20,249
# 2 AFG Afghanistan 1951 21,352
# 3 AFG Afghanistan 1952 22,532
# 4 AFG Afghanistan 1953 23,557
# 5 AFG Afghanistan 1954 24,555
# 6 ALB Albania 1950 8,097
# 7 ALB Albania 1951 8,986
# 8 ALB Albania 1952 10,058
# 9 ALB Albania 1953 11,123
#10 ALB Albania 1954 12,246
데이터
df1 <- structure(list(Code = structure(1:2, .Label = c("AFG", "ALB"), class = "factor"),
Country = structure(1:2, .Label = c("Afghanistan", "Albania"
), class = "factor"), `1950` = structure(1:2, .Label = c("20,249",
"8,097"), class = "factor"), `1951` = structure(1:2, .Label = c("21,352",
"8,986"), class = "factor"), `1952` = structure(2:1, .Label = c("10,058",
"22,532"), class = "factor"), `1953` = structure(2:1, .Label = c("11,123",
"23,557"), class = "factor"), `1954` = structure(2:1, .Label = c("12,246",
"24,555"), class = "factor")), class = "data.frame", row.names = c(NA,
-2L))
답변
이 답변은 태그로 설정되어 있기 때문에 r-FAQ, 나는 기초 R의 다른 대안을 공유하는 것이 유용 할 것이라고 생각했다 stack
.
그러나 s stack
에서는 작동하지 않습니다. is factor
경우에만 작동 하며의 설명서에서 다음 을 발견 할 수 있습니다.is.vector
TRUE
is.vector
is.vector
TRUE
x가 names 이외의 속성이없는 지정된 모드의 벡터이면를 반환 합니다 .FALSE
그렇지 않으면 반환 합니다.
@ Jaap ‘s answer 의 샘플 데이터 를 사용하고 있는데 , 여기서 연도 열의 값은 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
답변
gather
from 사용을 보여주는 또 다른 예는 다음과 같습니다 tidyr
. 열을 gather
개별적으로 제거하거나 (여기에서와 같이) 원하는 연도를 명시 적으로 포함 하여 열을 선택할 수 있습니다 .
쉼표를 처리하기 위해 (그리고 check.names = FALSE
설정되지 않은 경우 X가 추가됨 ) 텍스트 값을 다시 숫자로 변환하기 위해 from 을 사용하여 dplyr
mutate를 사용 하고 있습니다. 이것들은 모두의 일부 이므로 함께로드 할 수 있습니다parse_number
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
답변
여기에 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;")
모든 것을 입력하지 않고 쿼리를하려면 다음을 사용할 수 있습니다.
그것을 구현 한 G. Grothendieck 에게 감사 합니다.
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
. 보다 정교한 방식으로 쿼리를 작성하려면 다음 게시물을 살펴보십시오.
