red-datasets 0.1.0 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,27 @@
1
+ class TestDataset < Test::Unit::TestCase
2
+ sub_test_case("#clear_cache!") do
3
+ def setup
4
+ @dataset = Datasets::Iris.new
5
+ @cache_dir_path = @dataset.send(:cache_dir_path)
6
+ end
7
+
8
+ test("when the dataset is downloaded") do
9
+ @dataset.first # This ensures the dataset downloaded
10
+ existence = {before: @cache_dir_path.join("iris.csv").exist?}
11
+
12
+ @dataset.clear_cache!
13
+ existence[:after] = @cache_dir_path.join("iris.csv").exist?
14
+
15
+ assert_equal({before: true, after: false},
16
+ existence)
17
+ end
18
+
19
+ test("when the dataset is not downloaded") do
20
+ FileUtils.rmtree(@cache_dir_path.to_s, secure: true) if @cache_dir_path.exist?
21
+
22
+ assert_nothing_raised do
23
+ @dataset.clear_cache!
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,29 @@
1
+ class DownloaderTest < Test::Unit::TestCase
2
+ include Helper::Sandbox
3
+
4
+ sub_test_case("#download") do
5
+ def setup
6
+ setup_sandbox
7
+ end
8
+
9
+ def teardown
10
+ teardown_sandbox
11
+ end
12
+
13
+ test("too many redirection") do
14
+ first_url = "https://example.com/file"
15
+ last_url = "https://example.com/last_redirection"
16
+ expected_message = "too many redirections: #{first_url} .. #{last_url}"
17
+ output_path = @tmp_dir + "file"
18
+ downloader = Datasets::Downloader.new(first_url)
19
+
20
+ downloader.define_singleton_method(:start_http) do |url, headers|
21
+ raise Datasets::Downloader::TooManyRedirects, "too many redirections: #{last_url}"
22
+ end
23
+
24
+ assert_raise(Datasets::Downloader::TooManyRedirects.new(expected_message)) do
25
+ downloader.download(output_path)
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,383 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'pathname'
4
+ require 'tmpdir'
5
+
6
+ class EStatJapanTest < Test::Unit::TestCase
7
+ sub_test_case('app_id') do
8
+ def setup
9
+ ENV['ESTATJAPAN_APP_ID'] = nil
10
+ Datasets::EStatJapan.app_id = nil
11
+ end
12
+
13
+ test('nothing') do
14
+ assert_raise(Datasets::EStatJapan::ArgumentError) do
15
+ Datasets::EStatJapan::StatsData.new('test-data-id')
16
+ end
17
+ end
18
+
19
+ test('constructor') do
20
+ stats_data = Datasets::EStatJapan::StatsData.new('test-data-id', app_id: 'test_by_constructor')
21
+ assert_equal('test_by_constructor', stats_data.app_id)
22
+ end
23
+
24
+ test('env') do
25
+ ENV['ESTATJAPAN_APP_ID'] = 'test_by_env'
26
+ stats_data = Datasets::EStatJapan::StatsData.new('test-data-id')
27
+ assert_equal('test_by_env', stats_data.app_id)
28
+ end
29
+
30
+ test('configure') do
31
+ Datasets::EStatJapan.configure do |config|
32
+ config.app_id = 'test_by_configure'
33
+ end
34
+ stats_data = Datasets::EStatJapan::StatsData.new('test-data-id')
35
+ assert_equal('test_by_configure', stats_data.app_id)
36
+ end
37
+
38
+ test('env & configure') do
39
+ ENV['ESTATJAPAN_APP_ID'] = 'test_by_env'
40
+ Datasets::EStatJapan.configure do |config|
41
+ config.app_id = 'test_by_configure'
42
+ end
43
+ stats_data = Datasets::EStatJapan::StatsData.new('test-data-id')
44
+ assert_equal('test_by_configure', stats_data.app_id)
45
+ end
46
+
47
+ test('env & configure & constructor') do
48
+ ENV['ESTATJAPAN_APP_ID'] = 'test_by_env'
49
+ Datasets::EStatJapan.configure do |config|
50
+ config.app_id = 'test_by_configure'
51
+ end
52
+ stats_data = Datasets::EStatJapan::StatsData.new('test-data-id', app_id: 'test_by_constructor')
53
+ assert_equal('test_by_constructor', stats_data.app_id)
54
+ end
55
+ end
56
+
57
+ sub_test_case('url generation') do
58
+ def setup
59
+ ENV['ESTATJAPAN_APP_ID'] = nil
60
+ Datasets::EStatJapan.app_id = nil
61
+ end
62
+
63
+ test('generates url correctly') do
64
+ Datasets::EStatJapan.app_id = 'abcdef'
65
+ stats_data = Datasets::EStatJapan::StatsData.new('test-data-id')
66
+ stats_data_id = '000000'
67
+ stats_data.instance_eval do
68
+ @id = stats_data_id
69
+ @base_url = 'http://testurl/rest/2.1/app/json/getStatsData'
70
+ end
71
+ url = stats_data.send(:generate_url)
72
+ assert_equal(
73
+ 'http://testurl/rest/2.1/app/json/getStatsData' \
74
+ '?appId=abcdef&lang=J&statsDataId=000000&' \
75
+ 'metaGetFlg=Y&cntGetFlg=N&sectionHeaderFlg=1',
76
+ url.to_s
77
+ )
78
+ end
79
+ end
80
+
81
+ sub_test_case('parsing records') do
82
+ def setup
83
+ Datasets::EStatJapan.app_id = nil
84
+ # prepare test data
85
+ class_obj = [
86
+ {
87
+ "@name": 'table1',
88
+ "@id": 'tab',
89
+ "CLASS": {
90
+ "@level": '1',
91
+ "@code": '00001',
92
+ "@name": 'table1'
93
+ }
94
+ },
95
+ {
96
+ "@name": 'data1',
97
+ "@id": 'cat01',
98
+ "CLASS": {
99
+ "@level": '1',
100
+ "@code": 'data1',
101
+ "@name": 'data1_name'
102
+ }
103
+ },
104
+ {
105
+ "@name": 'area1',
106
+ "@id": 'area',
107
+ "CLASS": [
108
+ {
109
+ "@level": '2',
110
+ "@code": '01100',
111
+ "@name": 'test1 big-city',
112
+ "@parentCode": '01000'
113
+ },
114
+ {
115
+ "@level": '3',
116
+ "@code": '01101',
117
+ "@name": 'test1 big-city a-ku',
118
+ "@parentCode": '01100'
119
+ },
120
+ {
121
+ "@level": '3',
122
+ "@code": '01102',
123
+ "@name": 'test1 big-city b-ku',
124
+ "@parentCode": '01100'
125
+ },
126
+ {
127
+ "@level": '2',
128
+ "@code": '02555',
129
+ "@name": 'test2 a-city',
130
+ "@parentCode": '02000'
131
+ },
132
+ {
133
+ "@level": '2',
134
+ "@code": '02556',
135
+ "@name": 'test2 b-city',
136
+ "@parentCode": '02000'
137
+ }
138
+ ]
139
+ },
140
+ {
141
+ "@name": 'time',
142
+ "@id": 'time',
143
+ "CLASS": [
144
+ {
145
+ "@level": '1',
146
+ "@code": 'time1',
147
+ "@name": 'time1'
148
+ },
149
+ {
150
+ "@level": '1',
151
+ "@code": 'time2',
152
+ "@name": 'time2'
153
+ },
154
+ {
155
+ "@level": '1',
156
+ "@code": 'time3',
157
+ "@name": 'time3'
158
+ }
159
+ ]
160
+ }
161
+ ]
162
+ data_inf = class_obj[2][:CLASS].map do |entry|
163
+ [
164
+ {
165
+ "$": 1000,
166
+ "@area": entry[:@code],
167
+ "@cat01": 'data1',
168
+ "@tab": 'table1',
169
+ "@time": 'time1',
170
+ "@unit": 'person'
171
+ },
172
+ {
173
+ "$": 2000,
174
+ "@area": entry[:@code],
175
+ "@cat01": 'data1',
176
+ "@tab": 'table1',
177
+ "@time": 'time2',
178
+ "@unit": 'person'
179
+ }
180
+ ]
181
+ end.flatten
182
+ ## test record for `skip_nil_row: true`
183
+ data_inf << {
184
+ "$": 3000,
185
+ "@area": '02556',
186
+ "@cat01": 'data1',
187
+ "@tab": 'table1',
188
+ "@time": 'time3',
189
+ "@unit": 'person'
190
+ }
191
+ @response_data_default = {
192
+ 'GET_STATS_DATA' => {
193
+ 'RESULT' => {
194
+ 'STATUS' => 0,
195
+ 'ERROR_MSG' => 'succeeded'
196
+ },
197
+ 'STATISTICAL_DATA' => {
198
+ 'DATA_INF' => {
199
+ 'VALUE' => data_inf
200
+ },
201
+ 'CLASS_INF' => {
202
+ 'CLASS_OBJ' => class_obj
203
+ }
204
+ }
205
+ }
206
+ }
207
+
208
+ @tmp_dir = Dir.mktmpdir
209
+ @test_data_path = Pathname(File.join(@tmp_dir, '200-ok.json'))
210
+ ENV['ESTATJAPAN_APP_ID'] = 'test_appid_correct'
211
+ File.open(@test_data_path, 'w') do |f|
212
+ f.write(@response_data_default.to_json)
213
+ end
214
+ end
215
+
216
+ def teardown
217
+ FileUtils.remove_entry_secure(@test_data_path)
218
+ FileUtils.remove_entry_secure(@tmp_dir)
219
+ end
220
+
221
+ test('parsing records with default option') do
222
+ test_data_path = @test_data_path
223
+ stats_data = Datasets::EStatJapan::StatsData.new('test-data-id', app_id: 'valid')
224
+ stats_data.instance_eval do
225
+ @data_path = test_data_path
226
+ end
227
+
228
+ records = []
229
+ value_num = 0
230
+ stats_data.each do |record|
231
+ records << record
232
+ value_num += record.values.length
233
+ end
234
+ assert_equal(4, records.length)
235
+ assert_equal(4 * 2, value_num)
236
+ assert_equal(4, stats_data.areas.length)
237
+ assert_equal(3, stats_data.time_tables.length)
238
+ assert_equal(2, stats_data.time_tables.reject { |_k, v| v[:skip] }.to_h.length)
239
+ assert_equal(1, stats_data.columns.length)
240
+ assert_equal(2, stats_data.schema.length)
241
+ end
242
+
243
+ test('parsing records with hierarchy_selection') do
244
+ test_data_path = @test_data_path
245
+ stats_data = \
246
+ Datasets::EStatJapan::StatsData.new('test-data-id',
247
+ hierarchy_selection: 'parent')
248
+ stats_data.instance_eval do
249
+ @data_path = test_data_path
250
+ end
251
+ records = []
252
+ stats_data.each do |record|
253
+ records << record
254
+ end
255
+ assert_equal(3, records.length)
256
+ assert_equal(3, stats_data.areas.length)
257
+ assert_equal(3, stats_data.time_tables.length)
258
+ assert_equal(2, stats_data.time_tables.reject { |_k, v| v[:skip] }.to_h.length)
259
+ assert_equal(1, stats_data.columns.length)
260
+ assert_equal(2, stats_data.schema.length)
261
+
262
+ stats_data = \
263
+ Datasets::EStatJapan::StatsData.new('test-data-id',
264
+ hierarchy_selection: 'child')
265
+ stats_data.instance_eval do
266
+ @data_path = test_data_path
267
+ end
268
+ records = []
269
+ stats_data.each do |record|
270
+ records << record
271
+ end
272
+ assert_equal(4, records.length)
273
+ assert_equal(4, stats_data.areas.length)
274
+ assert_equal(3, stats_data.time_tables.length)
275
+ assert_equal(2, stats_data.time_tables.reject { |_k, v| v[:skip] }.to_h.length)
276
+ assert_equal(1, stats_data.columns.length)
277
+ assert_equal(2, stats_data.schema.length)
278
+
279
+ stats_data = \
280
+ Datasets::EStatJapan::StatsData.new('test-data-id',
281
+ hierarchy_selection: 'both')
282
+ stats_data.instance_eval do
283
+ @data_path = test_data_path
284
+ end
285
+ records = []
286
+ stats_data.each do |record|
287
+ records << record
288
+ end
289
+ assert_equal(5, records.length)
290
+ assert_equal(5, stats_data.areas.length)
291
+ assert_equal(3, stats_data.time_tables.length)
292
+ assert_equal(2, stats_data.time_tables.reject { |_k, v| v[:skip] }.to_h.length)
293
+ assert_equal(1, stats_data.columns.length)
294
+ assert_equal(2, stats_data.schema.length)
295
+ end
296
+
297
+ test('parsing records with skip_nil_(column|row)') do
298
+ test_data_path = @test_data_path
299
+ stats_data = \
300
+ Datasets::EStatJapan::StatsData.new('test-data-id',
301
+ skip_nil_column: false)
302
+ stats_data.instance_eval do
303
+ @data_path = test_data_path
304
+ end
305
+ records = []
306
+ value_num = 0
307
+ stats_data.each do |record|
308
+ records << record
309
+ value_num += record.values.length
310
+ end
311
+ assert_equal(4, records.length)
312
+ assert_equal(4 * 3, value_num)
313
+ assert_equal(4, stats_data.areas.length)
314
+ assert_equal(3, stats_data.time_tables.length)
315
+ assert_equal(3, stats_data.time_tables.reject { |_k, v| v[:skip] }.to_h.length)
316
+ assert_equal(1, stats_data.columns.length)
317
+ assert_equal(3, stats_data.schema.length)
318
+
319
+ stats_data = \
320
+ Datasets::EStatJapan::StatsData.new('test-data-id',
321
+ skip_nil_row: true,
322
+ skip_nil_column: false)
323
+ stats_data.instance_eval do
324
+ @data_path = test_data_path
325
+ end
326
+ records = []
327
+ value_num = 0
328
+ stats_data.each do |record|
329
+ records << record
330
+ value_num += record.values.length
331
+ end
332
+ assert_equal(1, records.length)
333
+ assert_equal(1 * 3, value_num)
334
+ assert_equal(4, stats_data.areas.length)
335
+ assert_equal(3, stats_data.time_tables.length)
336
+ assert_equal(3, stats_data.time_tables.reject { |_k, v| v[:skip] }.to_h.length)
337
+ assert_equal(1, stats_data.columns.length)
338
+ assert_equal(3, stats_data.schema.length)
339
+ end
340
+ end
341
+
342
+ sub_test_case('anomaly responses') do
343
+ def setup
344
+ ENV['ESTATJAPAN_APP_ID'] = nil
345
+ Datasets::EStatJapan.app_id = nil
346
+ @response_data = {
347
+ 'GET_STATS_DATA' => {
348
+ 'RESULT' => {
349
+ 'STATUS' => 100,
350
+ 'ERROR_MSG' => 'error message'
351
+ }
352
+ }
353
+ }
354
+ @tmp_dir = Dir.mktmpdir
355
+ @test_data_path = Pathname(File.join(@tmp_dir, '200-error.json'))
356
+ File.open(@test_data_path, 'w') do |f|
357
+ f.write(@response_data.to_json)
358
+ end
359
+ end
360
+
361
+ def teardown
362
+ FileUtils.remove_entry_secure(@tmp_dir)
363
+ end
364
+
365
+ test('forbidden access with invalid app_id') do
366
+ test_data_path = @test_data_path
367
+ ENV['ESTATJAPAN_APP_ID'] = 'test_appid_invalid'
368
+ stats_data = Datasets::EStatJapan::StatsData.new('test-data-id')
369
+ cache_file_path = nil
370
+ stats_data.instance_eval do
371
+ cache_file_path = @data_path = test_data_path
372
+ end
373
+ assert_raise(Datasets::EStatJapan::APIError) do
374
+ # contains no data
375
+ stats_data.each do |record|
376
+ record
377
+ end
378
+ end
379
+ # ensure remove error response cache
380
+ assert_equal(cache_file_path.exist?, false)
381
+ end
382
+ end
383
+ end
@@ -0,0 +1,251 @@
1
+ class PenguinsTest < Test::Unit::TestCase
2
+ sub_test_case("PenguinsRawData::SpeciesBase") do
3
+ test("#data_path") do
4
+ data_paths = [ Datasets::PenguinsRawData::Adelie,
5
+ Datasets::PenguinsRawData::Gentoo,
6
+ Datasets::PenguinsRawData::Chinstrap ].map {|cls|
7
+ dataset = cls.new
8
+ dataset.data_path.relative_path_from(dataset.send(:cache_dir_path)).to_s
9
+ }
10
+ assert_equal(["penguins/adelie.csv", "penguins/gentoo.csv", "penguins/chinstrap.csv"],
11
+ data_paths)
12
+ end
13
+ end
14
+
15
+ sub_test_case("Adelie") do
16
+ def setup
17
+ @dataset = Datasets::PenguinsRawData::Adelie.new
18
+ end
19
+
20
+ test("#each") do
21
+ records = @dataset.each.to_a
22
+ assert_equal([ 152,
23
+ {
24
+ study_name: "PAL0708",
25
+ sample_number: 1,
26
+ species: "Adelie Penguin (Pygoscelis adeliae)",
27
+ region: "Anvers",
28
+ island: "Torgersen",
29
+ stage: "Adult, 1 Egg Stage",
30
+ individual_id: "N1A1",
31
+ clutch_completion: "Yes",
32
+ date_egg: DateTime.new(2007, 11, 11),
33
+ culmen_length_mm: 39.1,
34
+ culmen_depth_mm: 18.7,
35
+ flipper_length_mm: 181,
36
+ body_mass_g: 3750,
37
+ sex: "MALE",
38
+ delta_15_n_permil: nil,
39
+ delta_13_c_permil: nil,
40
+ comments: "Not enough blood for isotopes."
41
+ },
42
+ {
43
+ study_name: "PAL0910",
44
+ sample_number: 152,
45
+ species: "Adelie Penguin (Pygoscelis adeliae)",
46
+ region: "Anvers",
47
+ island: "Dream",
48
+ stage: "Adult, 1 Egg Stage",
49
+ individual_id: "N85A2",
50
+ clutch_completion: "Yes",
51
+ date_egg: DateTime.new(2009, 11, 17),
52
+ culmen_length_mm: 41.5,
53
+ culmen_depth_mm: 18.5,
54
+ flipper_length_mm: 201,
55
+ body_mass_g: 4000,
56
+ sex: "MALE",
57
+ delta_15_n_permil: 8.89640,
58
+ delta_13_c_permil: -26.06967,
59
+ comments: nil
60
+ }
61
+ ],
62
+ [
63
+ records.size,
64
+ records[0].to_h,
65
+ records[-1].to_h
66
+ ])
67
+ end
68
+ end
69
+
70
+ sub_test_case("Gentoo") do
71
+ def setup
72
+ @dataset = Datasets::PenguinsRawData::Gentoo.new
73
+ end
74
+
75
+ test("#each") do
76
+ records = @dataset.each.to_a
77
+ assert_equal([ 124,
78
+ {
79
+ study_name: "PAL0708",
80
+ sample_number: 1,
81
+ species: "Gentoo penguin (Pygoscelis papua)",
82
+ region: "Anvers",
83
+ island: "Biscoe",
84
+ stage: "Adult, 1 Egg Stage",
85
+ individual_id: "N31A1",
86
+ clutch_completion: "Yes",
87
+ date_egg: DateTime.new(2007, 11, 27),
88
+ culmen_length_mm: 46.1,
89
+ culmen_depth_mm: 13.2,
90
+ flipper_length_mm: 211,
91
+ body_mass_g: 4500,
92
+ sex: "FEMALE",
93
+ delta_15_n_permil: 7.993,
94
+ delta_13_c_permil: -25.5139,
95
+ comments: nil
96
+ },
97
+ {
98
+ study_name: "PAL0910",
99
+ sample_number: 124,
100
+ species: "Gentoo penguin (Pygoscelis papua)",
101
+ region: "Anvers",
102
+ island: "Biscoe",
103
+ stage: "Adult, 1 Egg Stage",
104
+ individual_id: "N43A2",
105
+ clutch_completion: "Yes",
106
+ date_egg: DateTime.new(2009, 11, 22),
107
+ culmen_length_mm: 49.9,
108
+ culmen_depth_mm: 16.1,
109
+ flipper_length_mm: 213,
110
+ body_mass_g: 5400,
111
+ sex: "MALE",
112
+ delta_15_n_permil: 8.3639,
113
+ delta_13_c_permil: -26.15531,
114
+ comments: nil
115
+ }
116
+ ],
117
+ [
118
+ records.size,
119
+ records[0].to_h,
120
+ records[-1].to_h
121
+ ])
122
+ end
123
+ end
124
+
125
+ sub_test_case("Chinstrap") do
126
+ def setup
127
+ @dataset = Datasets::PenguinsRawData::Chinstrap.new
128
+ end
129
+
130
+ test("#each") do
131
+ records = @dataset.each.to_a
132
+ assert_equal([ 68,
133
+ {
134
+ study_name: "PAL0708",
135
+ sample_number: 1,
136
+ species: "Chinstrap penguin (Pygoscelis antarctica)",
137
+ region: "Anvers",
138
+ island: "Dream",
139
+ stage: "Adult, 1 Egg Stage",
140
+ individual_id: "N61A1",
141
+ clutch_completion: "No",
142
+ date_egg: DateTime.new(2007, 11, 19),
143
+ culmen_length_mm: 46.5,
144
+ culmen_depth_mm: 17.9,
145
+ flipper_length_mm: 192,
146
+ body_mass_g: 3500,
147
+ sex: "FEMALE",
148
+ delta_15_n_permil: 9.03935,
149
+ delta_13_c_permil: -24.30229,
150
+ comments: "Nest never observed with full clutch."
151
+ },
152
+ {
153
+ study_name: "PAL0910",
154
+ sample_number: 68,
155
+ species: "Chinstrap penguin (Pygoscelis antarctica)",
156
+ region: "Anvers",
157
+ island: "Dream",
158
+ stage: "Adult, 1 Egg Stage",
159
+ individual_id: "N100A2",
160
+ clutch_completion: "Yes",
161
+ date_egg: DateTime.new(2009, 11, 21),
162
+ culmen_length_mm: 50.2,
163
+ culmen_depth_mm: 18.7,
164
+ flipper_length_mm: 198,
165
+ body_mass_g: 3775,
166
+ sex: "FEMALE",
167
+ delta_15_n_permil: 9.39305,
168
+ delta_13_c_permil: -24.25255,
169
+ comments: nil
170
+ }
171
+ ],
172
+ [
173
+ records.size,
174
+ records[0].to_h,
175
+ records[-1].to_h
176
+ ])
177
+ end
178
+ end
179
+
180
+ sub_test_case("Penguins") do
181
+ def setup
182
+ @dataset = Datasets::Penguins.new
183
+ end
184
+
185
+ test("order of species") do
186
+ species_values = @dataset.map {|r| r.species }.uniq
187
+ assert_equal(["Adelie", "Chinstrap", "Gentoo"],
188
+ species_values)
189
+ end
190
+
191
+ test("data cleansing") do
192
+ sex_values = @dataset.map {|r| r.sex }.uniq.compact.sort
193
+ assert_equal(["female", "male"],
194
+ sex_values)
195
+ end
196
+
197
+ test("#each") do
198
+ records = @dataset.each.to_a
199
+ assert_equal([
200
+ 344,
201
+ {
202
+ species: "Adelie",
203
+ island: "Torgersen",
204
+ bill_length_mm: 39.1,
205
+ bill_depth_mm: 18.7,
206
+ flipper_length_mm: 181,
207
+ body_mass_g: 3750,
208
+ sex: "male",
209
+ year: 2007
210
+ },
211
+ {
212
+ species: "Chinstrap",
213
+ island: "Dream",
214
+ bill_length_mm: 46.5,
215
+ bill_depth_mm: 17.9,
216
+ flipper_length_mm: 192,
217
+ body_mass_g: 3500,
218
+ sex: "female",
219
+ year: 2007
220
+ },
221
+ {
222
+ species: "Gentoo",
223
+ island: "Biscoe",
224
+ bill_length_mm: 46.1,
225
+ bill_depth_mm: 13.2,
226
+ flipper_length_mm: 211,
227
+ body_mass_g: 4500,
228
+ sex: "female",
229
+ year: 2007
230
+ },
231
+ {
232
+ species: "Gentoo",
233
+ island: "Biscoe",
234
+ bill_length_mm: 49.9,
235
+ bill_depth_mm: 16.1,
236
+ flipper_length_mm: 213,
237
+ body_mass_g: 5400,
238
+ sex: "male",
239
+ year: 2009
240
+ }
241
+ ],
242
+ [
243
+ records.size,
244
+ records[0].to_h,
245
+ records[152].to_h,
246
+ records[220].to_h,
247
+ records[-1].to_h,
248
+ ])
249
+ end
250
+ end
251
+ end