7 데이터 가져오기
7.1 소개
R 패키지에서 제공하는 데이터로 작업하는 것은 데이터 과학 도구를 배우는 좋은 방법이지만, 언젠가는 배운 내용을 자신의 데이터에 적용하고 싶을 것입니다. 이 장에서는 데이터 파일을 R로 읽어오는 기본 사항을 배웁니다.
구체적으로 이 장에서는 일반 텍스트 사각형 파일(plain-text rectangular files)을 읽는 데 중점을 둘 것입니다. 열 이름, 유형, 결측 데이터와 같은 기능을 처리하기 위한 실용적인 조언으로 시작하겠습니다. 그런 다음 한 번에 여러 파일에서 데이터를 읽고 R에서 파일로 데이터를 쓰는 방법에 대해 배울 것입니다. 마지막으로 R에서 데이터 프레임을 직접 만드는 방법을 배울 것입니다.
7.1.1 선수 지식
이 장에서는 핵심 tidyverse의 일부인 readr 패키지를 사용하여 R에서 플랫 파일(flat files)을 로드하는 방법을 배웁니다.
7.2 파일에서 데이터 읽기
먼저 가장 일반적인 사각형 데이터 파일 유형인 CSV(comma-separated values, 쉼표로 구분된 값)에 초점을 맞출 것입니다. 간단한 CSV 파일의 모습은 다음과 같습니다. 일반적으로 헤더 행이라고 하는 첫 번째 행은 열 이름을 제공하고 다음 6개 행은 데이터를 제공합니다. 열은 쉼표로 구분(또는 구분자로 사용)됩니다.
Student ID,Full Name,favourite.food,mealPlan,AGE
1,Sunil Huffmann,Strawberry yoghurt,Lunch only,4
2,Barclay Lynn,French fries,Lunch only,5
3,Jayendra Lyne,N/A,Breakfast and lunch,7
4,Leon Rossini,Anchovies,Lunch only,
5,Chidiegwu Dunkel,Pizza,Breakfast and lunch,five
6,Güvenç Attila,Ice cream,Lunch only,6
Table 7.1 은 동일한 데이터를 표로 나타낸 것입니다.
| Student ID | Full Name | favourite.food | mealPlan | AGE |
|---|---|---|---|---|
| 1 | Sunil Huffmann | Strawberry yoghurt | Lunch only | 4 |
| 2 | Barclay Lynn | French fries | Lunch only | 5 |
| 3 | Jayendra Lyne | N/A | Breakfast and lunch | 7 |
| 4 | Leon Rossini | Anchovies | Lunch only | NA |
| 5 | Chidiegwu Dunkel | Pizza | Breakfast and lunch | five |
| 6 | Güvenç Attila | Ice cream | Lunch only | 6 |
read_csv()를 사용하여 이 파일을 R로 읽을 수 있습니다. 첫 번째 인수가 가장 중요합니다. 파일의 경로(path)입니다. 경로는 파일의 주소라고 생각할 수 있습니다. 파일 이름은 students.csv이고 data 폴더에 있습니다.
students <- read_csv("data/students.csv")
#> Rows: 6 Columns: 5
#> ── Column specification ─────────────────────────────────────────────────────
#> Delimiter: ","
#> chr (4): Full Name, favourite.food, mealPlan, AGE
#> dbl (1): Student ID
#>
#> ℹ Use `spec()` to retrieve the full column specification for this data.
#> ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.위의 코드는 프로젝트의 data 폴더에 students.csv 파일이 있는 경우 작동합니다. https://pos.it/r4ds-students-csv에서 students.csv 파일을 다운로드하거나 다음을 사용하여 해당 URL에서 직접 읽을 수 있습니다:
students <- read_csv("https://pos.it/r4ds-students-csv")read_csv()를 실행하면 데이터의 행과 열 수, 사용된 구분자, 열 사양(열에 포함된 데이터 유형별로 구성된 열 이름)을 알려주는 메시지가 출력됩니다. 또한 전체 열 사양을 검색하는 방법과 이 메시지를 끄는 방법에 대한 정보도 출력합니다. 이 메시지는 readr의 필수적인 부분이며 Section 7.3 에서 다시 다룰 것입니다.
7.2.1 실용적인 조언
데이터를 읽은 후 첫 번째 단계는 일반적으로 나머지 분석에서 작업하기 쉽도록 데이터를 어떤 식으로든 변형하는 것입니다. 그 점을 염두에 두고 students 데이터를 다시 살펴봅시다.
students
#> # A tibble: 6 × 5
#> `Student ID` `Full Name` favourite.food mealPlan AGE
#> <dbl> <chr> <chr> <chr> <chr>
#> 1 1 Sunil Huffmann Strawberry yoghurt Lunch only 4
#> 2 2 Barclay Lynn French fries Lunch only 5
#> 3 3 Jayendra Lyne N/A Breakfast and lunch 7
#> 4 4 Leon Rossini Anchovies Lunch only <NA>
#> 5 5 Chidiegwu Dunkel Pizza Breakfast and lunch five
#> 6 6 Güvenç Attila Ice cream Lunch only 6favourite.food 열에는 많은 음식 항목이 있고 그 다음 문자열 N/A가 있는데, 이는 R이 “사용할 수 없음(not available)”으로 인식하는 실제 NA였어야 합니다. 이것은 na 인수를 사용하여 해결할 수 있는 문제입니다. 기본적으로 read_csv()는 이 데이터셋의 빈 문자열("")만 NA로 인식하지만, 문자열 "N/A"도 인식하도록 하고 싶습니다.
students <- read_csv("data/students.csv", na = c("N/A", ""))
students
#> # A tibble: 6 × 5
#> `Student ID` `Full Name` favourite.food mealPlan AGE
#> <dbl> <chr> <chr> <chr> <chr>
#> 1 1 Sunil Huffmann Strawberry yoghurt Lunch only 4
#> 2 2 Barclay Lynn French fries Lunch only 5
#> 3 3 Jayendra Lyne <NA> Breakfast and lunch 7
#> 4 4 Leon Rossini Anchovies Lunch only <NA>
#> 5 5 Chidiegwu Dunkel Pizza Breakfast and lunch five
#> 6 6 Güvenç Attila Ice cream Lunch only 6Student ID와 Full Name 열이 역따옴표(backticks)로 둘러싸여 있는 것을 눈치챘을 수도 있습니다. 공백이 포함되어 있어 변수 이름에 대한 R의 일반적인 규칙을 위반하기 때문입니다. 이를 비구문적(non-syntactic) 이름이라고 합니다. 이러한 변수를 참조하려면 역따옴표 `로 감싸야 합니다:
students |>
rename(
student_id = `Student ID`,
full_name = `Full Name`
)
#> # A tibble: 6 × 5
#> student_id full_name favourite.food mealPlan AGE
#> <dbl> <chr> <chr> <chr> <chr>
#> 1 1 Sunil Huffmann Strawberry yoghurt Lunch only 4
#> 2 2 Barclay Lynn French fries Lunch only 5
#> 3 3 Jayendra Lyne <NA> Breakfast and lunch 7
#> 4 4 Leon Rossini Anchovies Lunch only <NA>
#> 5 5 Chidiegwu Dunkel Pizza Breakfast and lunch five
#> 6 6 Güvenç Attila Ice cream Lunch only 6대안적인 접근 방식은 janitor::clean_names()를 사용하여 몇 가지 휴리스틱을 사용해 모든 이름을 한 번에 스네이크 케이스(snake case)로 바꾸는 것입니다1.
students |> janitor::clean_names()
#> # A tibble: 6 × 5
#> student_id full_name favourite_food meal_plan age
#> <dbl> <chr> <chr> <chr> <chr>
#> 1 1 Sunil Huffmann Strawberry yoghurt Lunch only 4
#> 2 2 Barclay Lynn French fries Lunch only 5
#> 3 3 Jayendra Lyne <NA> Breakfast and lunch 7
#> 4 4 Leon Rossini Anchovies Lunch only <NA>
#> 5 5 Chidiegwu Dunkel Pizza Breakfast and lunch five
#> 6 6 Güvenç Attila Ice cream Lunch only 6데이터를 읽은 후의 또 다른 일반적인 작업은 변수 유형을 고려하는 것입니다. 예를 들어 meal_plan은 가능한 값 집합이 알려진 범주형 변수이며, R에서는 팩터(factor)로 표현되어야 합니다:
students |>
janitor::clean_names() |>
mutate(meal_plan = factor(meal_plan))
#> # A tibble: 6 × 5
#> student_id full_name favourite_food meal_plan age
#> <dbl> <chr> <chr> <fct> <chr>
#> 1 1 Sunil Huffmann Strawberry yoghurt Lunch only 4
#> 2 2 Barclay Lynn French fries Lunch only 5
#> 3 3 Jayendra Lyne <NA> Breakfast and lunch 7
#> 4 4 Leon Rossini Anchovies Lunch only <NA>
#> 5 5 Chidiegwu Dunkel Pizza Breakfast and lunch five
#> 6 6 Güvenç Attila Ice cream Lunch only 6meal_plan 변수의 값은 그대로 유지되었지만 변수 이름 아래에 표시된 변수 유형이 문자(<chr>)에서 팩터(<fct>)로 변경되었습니다. 팩터에 대해서는 Chapter 16 에서 더 자세히 배울 것입니다.
이 데이터를 분석하기 전에 아마도 age 열을 수정하고 싶을 것입니다. 현재 age는 관측값 중 하나가 숫자 5 대신 five로 입력되어 있기 때문에 문자 변수입니다. 이 문제를 해결하는 세부 사항은 Chapter 20 에서 논의합니다.
students <- students |>
janitor::clean_names() |>
mutate(
meal_plan = factor(meal_plan),
age = parse_number(if_else(age == "five", "5", age))
)
students
#> # A tibble: 6 × 5
#> student_id full_name favourite_food meal_plan age
#> <dbl> <chr> <chr> <fct> <dbl>
#> 1 1 Sunil Huffmann Strawberry yoghurt Lunch only 4
#> 2 2 Barclay Lynn French fries Lunch only 5
#> 3 3 Jayendra Lyne <NA> Breakfast and lunch 7
#> 4 4 Leon Rossini Anchovies Lunch only NA
#> 5 5 Chidiegwu Dunkel Pizza Breakfast and lunch 5
#> 6 6 Güvenç Attila Ice cream Lunch only 6여기서 새로운 함수는 if_else()로, 세 가지 인수가 있습니다. 첫 번째 인수 test는 논리형 벡터여야 합니다. 결과는 test가 TRUE일 때 두 번째 인수 yes의 값을, FALSE일 때 세 번째 인수 no의 값을 포함합니다. 여기서는 age가 문자열 "five"이면 "5"로 만들고, 그렇지 않으면 age 그대로 두라고 말하고 있습니다. if_else()와 논리형 벡터에 대해서는 Chapter 12 에서 더 자세히 배울 것입니다.
7.2.2 기타 인수
언급해야 할 다른 중요한 인수가 몇 가지 있는데, 편리한 트릭을 먼저 보여드리면 시연하기가 더 쉬울 것입니다. read_csv()는 CSV 파일처럼 만들고 서식을 지정한 텍스트 문자열을 읽을 수 있습니다:
read_csv(
"a,b,c
1,2,3
4,5,6"
)
#> # A tibble: 2 × 3
#> a b c
#> <dbl> <dbl> <dbl>
#> 1 1 2 3
#> 2 4 5 6일반적으로 read_csv()는 데이터의 첫 번째 줄을 열 이름으로 사용하는데, 이는 매우 일반적인 관례입니다. 하지만 파일 상단에 몇 줄의 메타데이터가 포함되는 경우도 드물지 않습니다. skip = n을 사용하여 처음 n 줄을 건너뛰거나 comment = "#"을 사용하여 (예를 들어) #로 시작하는 모든 줄을 삭제할 수 있습니다:
다른 경우에는 데이터에 열 이름이 없을 수도 있습니다. col_names = FALSE를 사용하여 read_csv()에 첫 번째 행을 헤더로 처리하지 말고 대신 X1에서 Xn까지 순차적으로 레이블을 지정하도록 지시할 수 있습니다:
read_csv(
"1,2,3
4,5,6",
col_names = FALSE
)
#> # A tibble: 2 × 3
#> X1 X2 X3
#> <dbl> <dbl> <dbl>
#> 1 1 2 3
#> 2 4 5 6또는 col_names에 문자 벡터를 전달하여 열 이름으로 사용할 수 있습니다:
이러한 인수들은 실제로 마주칠 대부분의 CSV 파일을 읽는 데 알아야 할 전부입니다. (나머지는 .csv 파일을 주의 깊게 검사하고 read_csv()의 다른 많은 인수에 대한 설명서를 읽어야 합니다.)
7.2.3 기타 파일 유형
read_csv()를 마스터하면 readr의 다른 기능을 사용하는 것은 간단합니다. 어떤 기능을 사용해야 하는지 알면 됩니다:
read_csv2()는 세미콜론으로 구분된 파일을 읽습니다. 이들은 필드를 구분하는 데,대신;을 사용하며 소수점 표시에,를 사용하는 국가에서 일반적입니다.read_tsv()는 탭으로 구분된 파일을 읽습니다.read_delim()은 구분자가 있는 파일을 읽으며, 지정하지 않으면 구분자를 자동으로 추측하려고 시도합니다.read_fwf()는 고정 너비 파일을 읽습니다.fwf_widths()로 너비로 필드를 지정하거나fwf_positions()로 위치로 필드를 지정할 수 있습니다.read_table()은 열이 공백으로 구분되는 고정 너비 파일의 일반적인 변형을 읽습니다.read_log()는 Apache 스타일의 로그 파일을 읽습니다.
7.2.4 연습문제
필드가 “|”로 구분된 파일을 읽으려면 어떤 함수를 사용하겠습니까?
file,skip,comment외에read_csv()와read_tsv()가 공통적으로 갖는 다른 인수는 무엇입니까?read_fwf()의 가장 중요한 인수는 무엇입니까?-
때때로 CSV 파일의 문자열에 쉼표가 포함되어 있습니다. 문제를 일으키지 않으려면
"또는'와 같은 인용 문자로 둘러싸야 합니다. 기본적으로read_csv()는 인용 문자가"일 것이라고 가정합니다. 다음 텍스트를 데이터 프레임으로 읽으려면read_csv()의 어떤 인수를 지정해야 합니까?"x,y\n1,'a,b'" -
다음 인라인 CSV 파일 각각에 무엇이 잘못되었는지 식별하세요. 코드를 실행하면 어떻게 됩니까?
-
다음 데이터 프레임에서 비구문적 이름을 참조하는 연습을 하세요:
-
1이라는 변수 추출하기. -
1대2의 산점도 그리기. -
2를1로 나눈3이라는 새 열 만들기. - 열 이름을
one,two,three로 바꾸기.
-
7.3 열 유형 제어
CSV 파일에는 각 변수의 유형(즉, 논리형인지, 숫자인지, 문자열인지 등)에 대한 정보가 포함되어 있지 않으므로 readr은 유형을 추측하려고 시도합니다. 이 섹션에서는 추측 프로세스가 작동하는 방식, 실패를 유발하는 몇 가지 일반적인 문제를 해결하는 방법, 필요한 경우 열 유형을 직접 제공하는 방법에 대해 설명합니다. 마지막으로 readr이 치명적으로 실패하고 파일 구조에 대한 더 많은 통찰력이 필요한 경우 유용한 몇 가지 일반적인 전략을 언급할 것입니다.
7.3.1 유형 추측
readr은 휴리스틱을 사용하여 열 유형을 파악합니다. 각 열에 대해 첫 번째 행에서 마지막 행까지 균등하게 간격을 둔 1,000개 행2의 값을 가져오며 결측값은 무시합니다. 그런 다음 다음 질문을 통해 작업합니다:
-
F,T,FALSE,TRUE만 포함합니까(대소문자 무시)? 그렇다면 논리형입니다. - 숫자만 포함합니까(예:
1,-4.5,5e6,Inf)? 그렇다면 숫자입니다. - ISO8601 표준과 일치합니까? 그렇다면 날짜 또는 날짜-시간입니다. (Section 17.2 에서 날짜-시간에 대해 더 자세히 다시 다룰 것입니다).
- 그렇지 않으면 문자열이어야 합니다.
이 간단한 예제에서 해당 동작을 실제로 볼 수 있습니다:
read_csv(
"\n logical,numeric,date,string
TRUE,1,2021-01-15,abc
false,4.5,2021-02-15,def
T,Inf,2021-02-16,ghi
")
#> # A tibble: 3 × 4
#> logical numeric date string
#> <lgl> <dbl> <date> <chr>
#> 1 TRUE 1 2021-01-15 abc
#> 2 FALSE 4.5 2021-02-15 def
#> 3 TRUE Inf 2021-02-16 ghi이 휴리스틱은 깨끗한 데이터셋이 있는 경우 잘 작동하지만, 실제로는 기이하고 아름다운 실패들을 마주하게 될 것입니다.
7.3.2 결측값, 열 유형 및 문제
열 감지가 실패하는 가장 일반적인 방법은 열에 예기치 않은 값이 포함되어 있어 더 구체적인 유형 대신 문자 열을 얻는 것입니다. 가장 일반적인 원인 중 하나는 readr이 예상하는 NA가 아닌 다른 것으로 기록된 결측값입니다.
이 간단한 1열 CSV 파일을 예로 들어보겠습니다:
simple_csv <- "
x
10
.
20
30"추가 인수 없이 읽으면 x는 문자 열이 됩니다:
read_csv(simple_csv)
#> # A tibble: 4 × 1
#> x
#> <chr>
#> 1 10
#> 2 .
#> 3 20
#> 4 30이 아주 작은 경우에는 결측값 .를 쉽게 볼 수 있습니다. 하지만 수천 개의 행이 있고 그 사이에 .로 표시된 결측값이 몇 개만 흩어져 있다면 어떻게 될까요? 한 가지 접근 방식은 readr에 x가 숫자 열이라고 알린 다음 어디에서 실패하는지 확인하는 것입니다. CSV 파일의 열 이름과 이름이 일치하는 명명된 리스트를 취하는 col_types 인수로 그렇게 할 수 있습니다:
df <- read_csv(
simple_csv,
col_types = list(x = col_double())
)
#> Warning: One or more parsing issues, call `problems()` on your data frame for
#> details, e.g.:
#> dat <- vroom(...)
#> problems(dat)이제 read_csv()는 문제가 있었다고 보고하고 problems()를 통해 더 많은 정보를 얻을 수 있다고 알려줍니다:
problems(df)
#> # A tibble: 1 × 5
#> row col expected actual file
#> <int> <int> <chr> <chr> <chr>
#> 1 3 1 a double . /private/var/folders/qc/wsq_wkqn6c37nz9rfqqpvp…이것은 3행 1열에 문제가 있었는데 readr은 double을 예상했지만 .을 얻었음을 알려줍니다. 이는 이 데이터셋이 결측값에 .을 사용한다는 것을 시사합니다. 그래서 na = "."을 설정하면 자동 추측이 성공하여 우리가 원하는 숫자 열을 얻게 됩니다:
read_csv(simple_csv, na = ".")
#> # A tibble: 4 × 1
#> x
#> <dbl>
#> 1 10
#> 2 NA
#> 3 20
#> 4 307.3.3 열 유형
readr은 사용자가 사용할 수 있는 총 9가지 열 유형을 제공합니다:
-
col_logical()및col_double()은 논리형 및 실수를 읽습니다. readr이 일반적으로 추측하므로 상대적으로 거의 필요하지 않습니다(위와 같은 경우 제외). -
col_integer()는 정수를 읽습니다. 이 책에서는 정수와 double이 기능적으로 동일하기 때문에 거의 구별하지 않지만, 정수가 double의 절반 메모리를 차지하므로 명시적으로 정수를 읽는 것이 가끔 유용할 수 있습니다. -
col_character()는 문자열을 읽습니다. 숫자 식별자, 즉 객체를 식별하지만 수학 연산을 적용하는 것이 의미가 없는 긴 숫자 시리즈인 열이 있을 때 명시적으로 지정하는 데 유용할 수 있습니다. 예로는 전화번호, 주민등록번호, 신용카드 번호 등이 있습니다. -
col_factor(),col_date(),col_datetime()은 각각 팩터, 날짜, 날짜-시간을 생성합니다. Chapter 16 및 Chapter 17 에서 해당 데이터 유형에 도달했을 때 자세히 배울 것입니다. -
col_number()는 숫자가 아닌 구성 요소를 무시하는 관대한 숫자 파서이며 통화에 특히 유용합니다. Chapter 13 에서 자세히 배울 것입니다. -
col_skip()은 열을 건너뛰어 결과에 포함되지 않도록 합니다. 이는 대용량 CSV 파일이 있고 일부 열만 사용하려는 경우 데이터 읽기 속도를 높이는 데 유용할 수 있습니다.
list()에서 cols()로 전환하고 .default를 지정하여 유형을 추측하는 기본 휴리스틱을 재정의하는 것도 가능합니다:
another_csv <- "
x,y,z
1,2,3"
read_csv(
another_csv,
col_types = cols(.default = col_character())
)
#> # A tibble: 1 × 3
#> x y z
#> <chr> <chr> <chr>
#> 1 1 2 3또 다른 유용한 도우미는 지정한 열만 읽어들이는 cols_only()입니다:
read_csv(
another_csv,
col_types = cols_only(x = col_character())
)
#> # A tibble: 1 × 1
#> x
#> <chr>
#> 1 17.4 여러 파일에서 데이터 읽기
때로는 데이터가 단일 파일에 포함되어 있는 대신 여러 파일로 나뉘어 있습니다. 예를 들어, 여러 달의 판매 데이터가 있고 각 달의 데이터가 별도 파일(01-sales.csv(1월), 02-sales.csv(2월), 03-sales.csv(3월))에 있을 수 있습니다. read_csv()를 사용하면 이 데이터를 한 번에 읽어서 단일 데이터 프레임에 서로 쌓을 수 있습니다.
sales_files <- c("data/01-sales.csv", "data/02-sales.csv", "data/03-sales.csv")
read_csv(sales_files, id = "file")
#> # A tibble: 19 × 6
#> file month year brand item n
#> <chr> <chr> <dbl> <dbl> <dbl> <dbl>
#> 1 data/01-sales.csv January 2019 1 1234 3
#> 2 data/01-sales.csv January 2019 1 8721 9
#> 3 data/01-sales.csv January 2019 1 1822 2
#> 4 data/01-sales.csv January 2019 2 3333 1
#> 5 data/01-sales.csv January 2019 2 2156 9
#> 6 data/01-sales.csv January 2019 2 3987 6
#> # ℹ 13 more rows다시 말하지만, 위의 코드는 프로젝트의 data 폴더에 CSV 파일이 있는 경우 작동합니다. https://pos.it/r4ds-01-sales, https://pos.it/r4ds-02-sales, https://pos.it/r4ds-03-sales에서 이 파일들을 다운로드하거나 다음을 사용하여 직접 읽을 수 있습니다:
id 인수는 데이터가 어떤 파일에서 왔는지 식별하는 file이라는 새 열을 결과 데이터 프레임에 추가합니다. 이는 읽어들이는 파일에 관측값을 원래 소스로 추적하는 데 도움이 되는 식별 열이 없는 경우 특히 유용합니다.
읽고 싶은 파일이 많으면 이름을 목록으로 작성하는 것이 번거로울 수 있습니다. 대신 기본 list.files() 함수를 사용하여 파일 이름의 패턴을 일치시켜 파일을 찾을 수 있습니다. Chapter 15 에서 이러한 패턴에 대해 더 자세히 배울 것입니다.
sales_files <- list.files("data", pattern = "sales\\.csv$", full.names = TRUE)
sales_files
#> [1] "data/01-sales.csv" "data/02-sales.csv" "data/03-sales.csv"7.5 파일에 쓰기
readr에는 데이터를 디스크에 다시 쓰는 두 가지 유용한 함수인 write_csv()와 write_tsv()도 함께 제공됩니다. 이 함수의 가장 중요한 인수는 x(저장할 데이터 프레임)와 file(저장할 위치)입니다. 또한 na로 결측값을 어떻게 쓸지 지정할 수 있고, 기존 파일에 append(추가)하고 싶은지 지정할 수 있습니다.
write_csv(students, "students.csv")이제 그 csv 파일을 다시 읽어 봅시다. CSV에 저장할 때 방금 설정한 변수 유형 정보가 손실된다는 점에 유의하세요. 일반 텍스트 파일에서 다시 읽기 시작하기 때문입니다:
students
#> # A tibble: 6 × 5
#> student_id full_name favourite_food meal_plan age
#> <dbl> <chr> <chr> <fct> <dbl>
#> 1 1 Sunil Huffmann Strawberry yoghurt Lunch only 4
#> 2 2 Barclay Lynn French fries Lunch only 5
#> 3 3 Jayendra Lyne <NA> Breakfast and lunch 7
#> 4 4 Leon Rossini Anchovies Lunch only NA
#> 5 5 Chidiegwu Dunkel Pizza Breakfast and lunch 5
#> 6 6 Güvenç Attila Ice cream Lunch only 6
write_csv(students, "students-2.csv")
read_csv("students-2.csv")
#> # A tibble: 6 × 5
#> student_id full_name favourite_food meal_plan age
#> <dbl> <chr> <chr> <chr> <dbl>
#> 1 1 Sunil Huffmann Strawberry yoghurt Lunch only 4
#> 2 2 Barclay Lynn French fries Lunch only 5
#> 3 3 Jayendra Lyne <NA> Breakfast and lunch 7
#> 4 4 Leon Rossini Anchovies Lunch only NA
#> 5 5 Chidiegwu Dunkel Pizza Breakfast and lunch 5
#> 6 6 Güvenç Attila Ice cream Lunch only 6이로 인해 CSV는 중간 결과를 캐싱하는 데 약간 신뢰할 수 없습니다. 로드할 때마다 열 사양을 다시 생성해야 하기 때문입니다. 두 가지 주요 대안이 있습니다:
-
write_rds()와read_rds()는 기본 함수인readRDS()와saveRDS()를 감싸는 균일한 래퍼입니다. 이들은 RDS라는 R의 사용자 정의 이진 형식으로 데이터를 저장합니다. 즉, 객체를 다시 로드할 때 저장한 것과 정확히 같은 R 객체를 로드하게 됩니다.write_rds(students, "students.rds") read_rds("students.rds") #> # A tibble: 6 × 5 #> student_id full_name favourite_food meal_plan age #> <dbl> <chr> <chr> <fct> <dbl> #> 1 1 Sunil Huffmann Strawberry yoghurt Lunch only 4 #> 2 2 Barclay Lynn French fries Lunch only 5 #> 3 3 Jayendra Lyne <NA> Breakfast and lunch 7 #> 4 4 Leon Rossini Anchovies Lunch only NA #> 5 5 Chidiegwu Dunkel Pizza Breakfast and lunch 5 #> 6 6 Güvenç Attila Ice cream Lunch only 6 -
arrow 패키지를 사용하면 프로그래밍 언어 간에 공유할 수 있는 빠른 이진 파일 형식인 parquet 파일을 읽고 쓸 수 있습니다. Chapter 22 에서 arrow에 대해 더 깊이 다룰 것입니다.
library(arrow) write_parquet(students, "students.parquet") read_parquet("students.parquet") #> # A tibble: 6 × 5 #> student_id full_name favourite_food meal_plan age #> <dbl> <chr> <chr> <fct> <dbl> #> 1 1 Sunil Huffmann Strawberry yoghurt Lunch only 4 #> 2 2 Barclay Lynn French fries Lunch only 5 #> 3 3 Jayendra Lyne NA Breakfast and lunch 7 #> 4 4 Leon Rossini Anchovies Lunch only NA #> 5 5 Chidiegwu Dunkel Pizza Breakfast and lunch 5 #> 6 6 Güvenç Attila Ice cream Lunch only 6
Parquet는 RDS보다 훨씬 빠르고 R 외부에서 사용할 수 있는 경향이 있지만 arrow 패키지가 필요합니다.
7.6 데이터 입력
때로는 R 스크립트에서 약간의 데이터 입력을 수행하여 “손으로” 티블을 조립해야 할 수도 있습니다. 이를 수행하는 데 도움이 되는 두 가지 유용한 함수가 있는데, 티블을 열별로 배치할지 행별로 배치할지에 따라 다릅니다. tibble()은 열별로 작동합니다:
열별로 데이터를 배치하면 행이 어떻게 관련되어 있는지 보기 어려울 수 있으므로 대안은 transposed tibble(전치된 티블)의 줄임말인 tribble()로, 데이터를 행별로 배치할 수 있습니다. tribble()은 코드 내 데이터 입력에 맞춤화되어 있습니다: 열 머리글은 ~로 시작하고 항목은 쉼표로 구분됩니다. 이를 통해 읽기 쉬운 형식으로 소량의 데이터를 배치할 수 있습니다:
tribble(
~x, ~y, ~z,
1, "h", 0.08,
2, "m", 0.83,
5, "g", 0.60
)
#> # A tibble: 3 × 3
#> x y z
#> <dbl> <chr> <dbl>
#> 1 1 h 0.08
#> 2 2 m 0.83
#> 3 5 g 0.67.7 요약
이 장에서는 read_csv()로 CSV 파일을 로드하는 방법과 tibble() 및 tribble()로 직접 데이터를 입력하는 방법을 배웠습니다. csv 파일이 작동하는 방식, 발생할 수 있는 문제, 극복 방법에 대해 배웠습니다. 이 책에서 데이터 가져오기에 대해 몇 번 더 다룰 것입니다: Chapter 20 에서는 Excel 및 Google Sheets에서, Chapter 21 에서는 데이터베이스에서 데이터를 로드하는 방법을, Chapter 22 에서는 parquet 파일에서, Chapter 23 에서는 JSON에서, Chapter 24 에서는 웹사이트에서 데이터를 로드하는 방법을 보여줄 것입니다.
이 책의 이 섹션은 거의 끝났지만 다뤄야 할 중요한 마지막 주제가 하나 있습니다: 도움을 받는 방법입니다. 따라서 다음 장에서는 도움을 찾을 수 있는 좋은 곳, 좋은 도움을 받을 가능성을 극대화하기 위해 reprex(재현 가능한 예제)를 만드는 방법, R의 세계를 따라잡기 위한 몇 가지 일반적인 조언을 배울 것입니다.