사용데이터 : https://2stndard.tistory.com/68
데이터 구조 변환(reshape)
tidyverse
생태계에서 가장 기본적인 전제는 데이터가 간결히 정제(tidy)되어야 한다는 것이다. 이 간결히 정제된 데이터는 원본 데이터(raw data)에서는 적용이 가능하다. 하지만 전처리가 시작되면 간결히 정제된 데이터로 유지하기 어려울 경우도 있고 경우에 따라서는 일부러 정제되지 않은 데이터로 변환해야 할 경우가 있다. 정제되지 않은 데이터는 긴(long) 형태의 데이터와 넓은(wide) 형태의 데이터 두가지 종류로 구분된다.
긴 형태의 데이터와 넓은 형태의 데이터
긴 형태의 데이터는 열로 표현된 변수들을 행 방향으로 풀어 넣음으로써 열의 개수는 줄고 행의 개수는 늘어나는 형태의 데이터이다. 긴 형태의 데이터는 이 책에서 중점적으로 설명할 데이터 시각화에 매우 적합한 형태이다.
긴 형태의 데이터는 R에서 데이터 핸들링부터 머신러닝 알고리즘을 사용한 데이터 분석 및 예측까지에서 가장 많이 사용되는 Hadley Wickam의 ‘tidyverse’ 생태계에서 정의하는 ’tidy’한 데이터의 전형이다. 이 tidy한 데이터는 각 열은 자체 변수이고, 각 행은 하나의 관찰이며 각 셀은 하나의 값으로 표현된다.
긴 형태의 데이터와 팩터를 잘 활용하면 짧고 읽기 쉬운 코드로 데이터 시각화가 가능하다는 장점이 있다. 특히 긴 형태의 데이터에서는 NA를 최소화할 수 있다는 장점을 지닌다. 위의 그림과 같이 여러 열로 표현된 넓은 형태의 데이터는 모든 열에 해당한 데이터가 존재하지 않는다면 이들을 NA로 처리해야하기 떄문에 당연히 NA가 늘어나게 되어 이를 처리하는데 추가적인 작업이 필요할 수 있다.
하지만 긴 형태의 데이터는 사람이 데이터를 읽고 판단하기에 매우 부적합하는 단점이 있다.
반면 넓은 형태의 데이터는 행로 표현된 변수들을 열 방향으로 풀어 넣음으로써 행의 개수는 줄고 열의 개수는 늘어나는 형태의 데이터이다. 위의 그림에서와 같이 넓은 형태의 데이터는 사용자가 직관적으로 데이터의 전반적 분포를 살펴보기가 좋지만 긴 형태의 데이터는 사용자가 전체적인 데이터를 살펴보기가 어렵다. 또 넓은 형식을 사용하면 필드에 데이터를 쉽게 입력할 수 있기 때문에 데이터를 넓은 형식으로 시작하는 것이 일반적이다.
반면 앞에서 지적한 바와 같이 데이터에 NA가 다소 많아지게 되고 열의 수가 많아지기 때문에 빅데이터 연산에 많이 사용되는 벡터 연산에 적절하지 않다. 벡터 연산을 적용하기 위해서 대부분 각 열을 벡터화하여 이 벡터 단위로 연산하는 경우가 많은데 이렇게 벡터의 개수가 많으면 벡터 연산을 여러번 실행하여야 한다는 단점이 존재한다.
긴 형태의 데이터 변환
긴 형태의 데이터를 만들기 위해서는 tidyr
패키지에서 제공하는 gather()
또는 pivot_longer()
를 사용한다. tidyr
의 공식 매뉴얼에 의하면 gather()
의 개발은 완료되었고 향후 pivot_longer()
로 전환되어 사용을 권고한다고 표기되어 있다. 따라서 pivot_longer()
를 위주로 설명하겠다.
pivot_longer(data, cols, names_to = “name”, names_prefix = NULL, names_sep = NULL, names_pattern = NULL, names_ptypes = list(), names_transform = list(), names_repair = “check_unique”, values_to = “value”, values_drop_na = FALSE, values_ptypes = list(), values_transform = list(), …) - data : 긴 형태로 만들 데이터프레임 - cols : 긴 형태로 만들 열 이름 벡터, 열 번호, 열 번호 범위 등 - names_to : cols에서 지정한 열 이름으로 구성될 열의 이름 - values_to : 각 셀의 값을 저장할 열 이름
pivot_longer()
를 사용하기 위해서 반드시 data
, cols
의 두가지 매개변수가 필수적으로 필요하고 보통 names_to
, values_to
까지 네 가지 매개변수를 설정한다. data
는 긴 형태로 변환할 데이터 프레임을 지정하는데 pipe(|>
나 %>%
)를 사용하면 생략될 수 있다. cols
는 긴 형태로 변환할 때 하나의 열로 합쳐질 열을 벡터로 설정한다. cols
는 하나 이상의 열을 지정해야하기 때문에 열 이름 벡터, 열 번호, 열 번호 시퀀스 등으로 설정할 수 있다. names_to
는 cols
로 합쳐질 열의 이름을 설정하고 values_to
는 합쳐질 열의 데이터가 저장될 열의 이름을 설정한다. names_to
와 values_to
를 설정하지 않으면 각각 ‘name’, ’value’로 자동 설정된다.
pivot_longer()
를 실습하기 위해서 본 포스트에서 사용하는 데이터의 df_covid19_100를 먼저 넓은 형태의 데이터로 다음과 같이 전환해보겠다.
df_wider <- df_covid19_100 |>
select(date, location, total_cases, new_cases, total_deaths, new_deaths)
df_wider
## # A tibble: 707 x 6
## date location total_cases new_cases total_deaths new_deaths
## <date> <fct> <dbl> <dbl> <dbl> <dbl>
## 1 2022-01-18 아프리카 10446204 26951 234504 317
## 2 2022-01-18 아시아 91658433 572629 1278156 1287
## 3 2022-01-18 유럽 107865438 1520977 1582414 3851
## 4 2022-01-18 북미 79545882 1185873 1257391 2936
## 5 2022-01-18 오세아니아 2128565 85220 5163 70
## 6 2022-01-18 남미 43721308 369086 1199893 828
## 7 2022-01-18 한국 705902 5800 6452 74
## 8 2022-01-19 아프리카 10481433 35229 234734 230
## 9 2022-01-19 아시아 92507804 849371 1279360 1204
## 10 2022-01-19 유럽 109463174 1597736 1585693 3279
## # ... with 697 more rows
이 넓은 형태의 데이터를 긴 형태의 데이터로 바꾸는 방법은 다음과 같이 세개의 방법을 사용할 수 있다. 첫 번째는 열 이름 벡터로, 두 번째 코드는 열 번호 벡터로, 세번째 코드는 시퀀스를 이용한 열 번호 벡터를 사용하는 방법이다.
df_wider |>
pivot_longer(cols = c('total_cases', 'new_cases', 'total_deaths', 'new_deaths'))
## # A tibble: 2,828 x 4
## date location name value
## <date> <fct> <chr> <dbl>
## 1 2022-01-18 아프리카 total_cases 10446204
## 2 2022-01-18 아프리카 new_cases 26951
## 3 2022-01-18 아프리카 total_deaths 234504
## 4 2022-01-18 아프리카 new_deaths 317
## 5 2022-01-18 아시아 total_cases 91658433
## 6 2022-01-18 아시아 new_cases 572629
## 7 2022-01-18 아시아 total_deaths 1278156
## 8 2022-01-18 아시아 new_deaths 1287
## 9 2022-01-18 유럽 total_cases 107865438
## 10 2022-01-18 유럽 new_cases 1520977
## # ... with 2,818 more rows
df_wider |> pivot_longer(c(3, 4, 5, 6), names_to = '구분', values_to = 'persons')
## # A tibble: 2,828 x 4
## date location 구분 persons
## <date> <fct> <chr> <dbl>
## 1 2022-01-18 아프리카 total_cases 10446204
## 2 2022-01-18 아프리카 new_cases 26951
## 3 2022-01-18 아프리카 total_deaths 234504
## 4 2022-01-18 아프리카 new_deaths 317
## 5 2022-01-18 아시아 total_cases 91658433
## 6 2022-01-18 아시아 new_cases 572629
## 7 2022-01-18 아시아 total_deaths 1278156
## 8 2022-01-18 아시아 new_deaths 1287
## 9 2022-01-18 유럽 total_cases 107865438
## 10 2022-01-18 유럽 new_cases 1520977
## # ... with 2,818 more rows
df_wider |> pivot_longer(3:6, names_to = '구분', values_to = 'persons')
## # A tibble: 2,828 x 4
## date location 구분 persons
## <date> <fct> <chr> <dbl>
## 1 2022-01-18 아프리카 total_cases 10446204
## 2 2022-01-18 아프리카 new_cases 26951
## 3 2022-01-18 아프리카 total_deaths 234504
## 4 2022-01-18 아프리카 new_deaths 317
## 5 2022-01-18 아시아 total_cases 91658433
## 6 2022-01-18 아시아 new_cases 572629
## 7 2022-01-18 아시아 total_deaths 1278156
## 8 2022-01-18 아시아 new_deaths 1287
## 9 2022-01-18 유럽 total_cases 107865438
## 10 2022-01-18 유럽 new_cases 1520977
## # ... with 2,818 more rows
넓은 형태의 데이터
넓은 형태의 데이터를 만들기 위해서는 tidyr
패키지에서 제공하는 spread()
또는 pivot_wider()
를 사용한다. gather()
와 마찬가지로 tidyr
의 공식 매뉴얼에 의하면 spread()
의 개발은 완료되었고 향후 pivot_wider()
로 전환되어 사용을 권고한다고 표기되어 있다. 따라서 pivot_wider()
를 위주로 설명하겠다.
pivot_wider(data, id_cols = NULL, names_from = name, names_prefix = ““, names_sep =”_“, names_glue = NULL, names_sort = FALSE, names_repair =”check_unique”, values_from = value, values_fill = NULL, values_fn = NULL, …) - data : 긴 형태로 만들 데이터프레임 - names_from : 열 이름으로 구성될 열의 이름 - values_from : 각 셀의 값으로 구성될 열 이름
pivot_wider()
를 사용하기 위해서 반드시 data
, names_from
, values_from
의 세 가지 매개변수가 필수적으로 필요하다. data
는 넓은 형태로 변환할 데이터 프레임을 지정하는데 pipe(|>
나 %>%
)를 사용하면 생략될 수 있다. names_from
은 넓은 형태로 변환할 때 열 이름으로 펼쳐질 데이터가 저장된 열을 설정한다. values_from
은 names_from
으로 펼쳐진 열에 저장될 데이터가 저장된 열을 설정한다.
pivot_wider()
를 실습하기 위해서 본 포스트에서 사용하는 데이터의 df_covid19_100를 먼저 긴 형태의 데이터로 다음과 같이 전환해보겠다.
df_longer <- df_covid19_100 |>
select(date, location, total_cases)
df_longer
## # A tibble: 707 x 3
## date location total_cases
## <date> <fct> <dbl>
## 1 2022-01-18 아프리카 10446204
## 2 2022-01-18 아시아 91658433
## 3 2022-01-18 유럽 107865438
## 4 2022-01-18 북미 79545882
## 5 2022-01-18 오세아니아 2128565
## 6 2022-01-18 남미 43721308
## 7 2022-01-18 한국 705902
## 8 2022-01-19 아프리카 10481433
## 9 2022-01-19 아시아 92507804
## 10 2022-01-19 유럽 109463174
## # ... with 697 more rows
이렇게 길게 생성된 데이터를 넓은 형태로 변환하기 위해서는 우선 열로 사용할 변수를 설정하여야 하는데 여기서는 각 대륙별로 열을 펼치고 각각의 대륙에 ‘total_cases’ 데이터를 저장하는 코드는 다음과 같다.
df_longer |>
pivot_wider(names_from = location, values_from = total_cases)
## # A tibble: 101 x 8
## date 아프리카 아시아 유럽 북미 오세아니아 남미 한국
## <date> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 2022-01-18 10446204 91658433 107865438 79545882 2128565 43721308 705902
## 2 2022-01-19 10481433 92507804 109463174 80623224 2197384 44181939 712503
## 3 2022-01-20 10530788 93222825 111090014 81419617 2261818 44635486 719269
## 4 2022-01-21 10568210 93942144 112691756 82422002 2306022 45066178 726274
## 5 2022-01-22 10609278 94623085 113970416 82756200 2373663 45452780 733902
## 6 2022-01-23 10625760 95222958 115002903 83227036 2406091 45757226 741413
## 7 2022-01-24 10652684 95977454 116321732 84197652 2466338 46048605 749979
## 8 2022-01-25 10708754 96687023 118127733 84805519 2520592 46465897 762983
## 9 2022-01-26 10742258 97439805 119899381 85479827 2572899 46843672 777497
## 10 2022-01-27 10779762 98141834 121749700 86093967 2640481 47328453 793582
## # ... with 91 more rows
'데이터 전처리' 카테고리의 다른 글
데이터 행의 제거 in R (0) | 2022.06.04 |
---|---|
빈도표(분할표, Contingency table)로 데이터 개수, 비율 구하기 in R (0) | 2022.06.04 |
apply, lapply, sapply, tapply in R (0) | 2022.03.12 |
for loop, apply, 벡터 연산의 속도 차이 in R (0) | 2022.02.26 |
색 in R (0) | 2022.02.24 |
댓글