polars-df 0.15.0 → 0.26.0

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.
Files changed (206) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +274 -0
  3. data/Cargo.lock +1465 -867
  4. data/Cargo.toml +3 -0
  5. data/LICENSE.txt +2 -2
  6. data/README.md +87 -37
  7. data/ext/polars/Cargo.toml +47 -16
  8. data/ext/polars/src/c_api/allocator.rs +7 -0
  9. data/ext/polars/src/c_api/mod.rs +1 -0
  10. data/ext/polars/src/catalog/mod.rs +1 -0
  11. data/ext/polars/src/catalog/unity.rs +470 -0
  12. data/ext/polars/src/conversion/any_value.rs +99 -84
  13. data/ext/polars/src/conversion/categorical.rs +30 -0
  14. data/ext/polars/src/conversion/chunked_array.rs +71 -62
  15. data/ext/polars/src/conversion/datetime.rs +63 -0
  16. data/ext/polars/src/conversion/mod.rs +796 -312
  17. data/ext/polars/src/dataframe/construction.rs +6 -18
  18. data/ext/polars/src/dataframe/export.rs +30 -39
  19. data/ext/polars/src/dataframe/general.rs +294 -362
  20. data/ext/polars/src/dataframe/io.rs +33 -150
  21. data/ext/polars/src/dataframe/map.rs +175 -0
  22. data/ext/polars/src/dataframe/mod.rs +37 -5
  23. data/ext/polars/src/dataframe/serde.rs +23 -8
  24. data/ext/polars/src/error.rs +44 -7
  25. data/ext/polars/src/exceptions.rs +21 -8
  26. data/ext/polars/src/expr/array.rs +86 -22
  27. data/ext/polars/src/expr/binary.rs +50 -1
  28. data/ext/polars/src/expr/bitwise.rs +39 -0
  29. data/ext/polars/src/expr/categorical.rs +20 -0
  30. data/ext/polars/src/expr/datatype.rs +51 -0
  31. data/ext/polars/src/expr/datetime.rs +99 -41
  32. data/ext/polars/src/expr/extension.rs +12 -0
  33. data/ext/polars/src/expr/general.rs +252 -128
  34. data/ext/polars/src/expr/list.rs +56 -60
  35. data/ext/polars/src/expr/meta.rs +30 -35
  36. data/ext/polars/src/expr/mod.rs +28 -6
  37. data/ext/polars/src/expr/name.rs +29 -14
  38. data/ext/polars/src/expr/rolling.rs +111 -3
  39. data/ext/polars/src/expr/selector.rs +219 -0
  40. data/ext/polars/src/expr/serde.rs +28 -0
  41. data/ext/polars/src/expr/string.rs +118 -20
  42. data/ext/polars/src/expr/struct.rs +14 -1
  43. data/ext/polars/src/file.rs +194 -86
  44. data/ext/polars/src/functions/aggregation.rs +13 -12
  45. data/ext/polars/src/functions/business.rs +2 -3
  46. data/ext/polars/src/functions/eager.rs +3 -2
  47. data/ext/polars/src/functions/io.rs +90 -18
  48. data/ext/polars/src/functions/lazy.rs +267 -118
  49. data/ext/polars/src/functions/meta.rs +8 -7
  50. data/ext/polars/src/functions/misc.rs +1 -1
  51. data/ext/polars/src/functions/mod.rs +2 -1
  52. data/ext/polars/src/functions/range.rs +88 -31
  53. data/ext/polars/src/functions/strings.rs +6 -0
  54. data/ext/polars/src/functions/utils.rs +8 -0
  55. data/ext/polars/src/interop/arrow/mod.rs +52 -1
  56. data/ext/polars/src/interop/arrow/{to_ruby.rs → to_rb.rs} +37 -7
  57. data/ext/polars/src/interop/arrow/to_rust.rs +43 -0
  58. data/ext/polars/src/interop/numo/to_numo_df.rs +1 -1
  59. data/ext/polars/src/interop/numo/to_numo_series.rs +72 -50
  60. data/ext/polars/src/io/cloud_options.rs +107 -0
  61. data/ext/polars/src/io/mod.rs +4 -0
  62. data/ext/polars/src/io/scan_options.rs +113 -0
  63. data/ext/polars/src/io/sink_options.rs +46 -0
  64. data/ext/polars/src/io/sink_output.rs +21 -0
  65. data/ext/polars/src/lazyframe/exitable.rs +39 -0
  66. data/ext/polars/src/lazyframe/general.rs +846 -368
  67. data/ext/polars/src/lazyframe/mod.rs +58 -5
  68. data/ext/polars/src/lazyframe/optflags.rs +59 -0
  69. data/ext/polars/src/lazyframe/serde.rs +36 -4
  70. data/ext/polars/src/lazyframe/sink.rs +46 -0
  71. data/ext/polars/src/lazygroupby.rs +38 -9
  72. data/ext/polars/src/lib.rs +574 -165
  73. data/ext/polars/src/map/lazy.rs +44 -74
  74. data/ext/polars/src/map/mod.rs +18 -254
  75. data/ext/polars/src/map/series.rs +241 -1087
  76. data/ext/polars/src/on_startup.rs +192 -9
  77. data/ext/polars/src/prelude.rs +1 -0
  78. data/ext/polars/src/rb_modules.rs +10 -57
  79. data/ext/polars/src/ruby/exceptions.rs +26 -0
  80. data/ext/polars/src/ruby/gvl.rs +104 -0
  81. data/ext/polars/src/ruby/lazy.rs +46 -0
  82. data/ext/polars/src/ruby/mod.rs +11 -0
  83. data/ext/polars/src/ruby/numo.rs +52 -0
  84. data/ext/polars/src/ruby/plan_callback.rs +198 -0
  85. data/ext/polars/src/ruby/rb_modules.rs +16 -0
  86. data/ext/polars/src/ruby/ruby_convert_registry.rs +51 -0
  87. data/ext/polars/src/ruby/ruby_function.rs +11 -0
  88. data/ext/polars/src/ruby/ruby_udf.rs +164 -0
  89. data/ext/polars/src/ruby/thread.rs +65 -0
  90. data/ext/polars/src/ruby/utils.rs +39 -0
  91. data/ext/polars/src/series/aggregation.rs +116 -91
  92. data/ext/polars/src/series/arithmetic.rs +16 -22
  93. data/ext/polars/src/series/comparison.rs +101 -222
  94. data/ext/polars/src/series/construction.rs +80 -70
  95. data/ext/polars/src/series/export.rs +98 -56
  96. data/ext/polars/src/series/general.rs +323 -440
  97. data/ext/polars/src/series/import.rs +22 -5
  98. data/ext/polars/src/series/map.rs +103 -0
  99. data/ext/polars/src/series/mod.rs +57 -15
  100. data/ext/polars/src/series/scatter.rs +139 -82
  101. data/ext/polars/src/sql.rs +16 -9
  102. data/ext/polars/src/testing/frame.rs +31 -0
  103. data/ext/polars/src/testing/mod.rs +5 -0
  104. data/ext/polars/src/testing/series.rs +31 -0
  105. data/ext/polars/src/timeout.rs +105 -0
  106. data/ext/polars/src/utils.rs +105 -4
  107. data/lib/polars/array_expr.rb +500 -22
  108. data/lib/polars/array_name_space.rb +384 -10
  109. data/lib/polars/batched_csv_reader.rb +48 -66
  110. data/lib/polars/binary_expr.rb +217 -0
  111. data/lib/polars/binary_name_space.rb +155 -1
  112. data/lib/polars/cat_expr.rb +224 -0
  113. data/lib/polars/cat_name_space.rb +132 -32
  114. data/lib/polars/catalog/unity/catalog_info.rb +20 -0
  115. data/lib/polars/catalog/unity/column_info.rb +31 -0
  116. data/lib/polars/catalog/unity/namespace_info.rb +21 -0
  117. data/lib/polars/catalog/unity/table_info.rb +50 -0
  118. data/lib/polars/catalog.rb +448 -0
  119. data/lib/polars/collect_batches.rb +22 -0
  120. data/lib/polars/config.rb +3 -3
  121. data/lib/polars/convert.rb +201 -36
  122. data/lib/polars/data_frame.rb +2851 -1017
  123. data/lib/polars/data_frame_plot.rb +173 -0
  124. data/lib/polars/data_type_expr.rb +52 -0
  125. data/lib/polars/data_type_group.rb +6 -0
  126. data/lib/polars/data_types.rb +118 -18
  127. data/lib/polars/date_time_expr.rb +426 -84
  128. data/lib/polars/date_time_name_space.rb +384 -111
  129. data/lib/polars/dynamic_group_by.rb +102 -10
  130. data/lib/polars/exceptions.rb +50 -5
  131. data/lib/polars/expr.rb +2159 -915
  132. data/lib/polars/extension_expr.rb +39 -0
  133. data/lib/polars/extension_name_space.rb +39 -0
  134. data/lib/polars/functions/aggregation/horizontal.rb +11 -6
  135. data/lib/polars/functions/aggregation/vertical.rb +2 -3
  136. data/lib/polars/functions/as_datatype.rb +290 -8
  137. data/lib/polars/functions/business.rb +95 -0
  138. data/lib/polars/functions/col.rb +6 -5
  139. data/lib/polars/functions/datatype.rb +62 -0
  140. data/lib/polars/functions/eager.rb +426 -24
  141. data/lib/polars/functions/escape_regex.rb +21 -0
  142. data/lib/polars/functions/lazy.rb +813 -195
  143. data/lib/polars/functions/lit.rb +21 -10
  144. data/lib/polars/functions/range/int_range.rb +74 -2
  145. data/lib/polars/functions/range/linear_space.rb +195 -0
  146. data/lib/polars/functions/range/time_range.rb +1 -1
  147. data/lib/polars/functions/repeat.rb +7 -12
  148. data/lib/polars/functions/whenthen.rb +2 -2
  149. data/lib/polars/group_by.rb +188 -58
  150. data/lib/polars/iceberg_dataset.rb +108 -0
  151. data/lib/polars/in_process_query.rb +37 -0
  152. data/lib/polars/io/cloud.rb +18 -0
  153. data/lib/polars/io/csv.rb +336 -128
  154. data/lib/polars/io/database.rb +19 -4
  155. data/lib/polars/io/delta.rb +134 -0
  156. data/lib/polars/io/iceberg.rb +34 -0
  157. data/lib/polars/io/ipc.rb +63 -63
  158. data/lib/polars/io/json.rb +16 -0
  159. data/lib/polars/io/lines.rb +172 -0
  160. data/lib/polars/io/ndjson.rb +176 -20
  161. data/lib/polars/io/parquet.rb +173 -95
  162. data/lib/polars/io/scan_options.rb +55 -0
  163. data/lib/polars/io/sink_options.rb +27 -0
  164. data/lib/polars/io/utils.rb +17 -0
  165. data/lib/polars/lazy_frame.rb +3017 -622
  166. data/lib/polars/lazy_group_by.rb +436 -2
  167. data/lib/polars/list_expr.rb +551 -59
  168. data/lib/polars/list_name_space.rb +465 -51
  169. data/lib/polars/meta_expr.rb +146 -24
  170. data/lib/polars/name_expr.rb +87 -2
  171. data/lib/polars/query_opt_flags.rb +264 -0
  172. data/lib/polars/rolling_group_by.rb +90 -5
  173. data/lib/polars/scan_cast_options.rb +86 -0
  174. data/lib/polars/schema.rb +128 -0
  175. data/lib/polars/selector.rb +245 -0
  176. data/lib/polars/selectors.rb +1048 -201
  177. data/lib/polars/series.rb +2522 -774
  178. data/lib/polars/series_plot.rb +72 -0
  179. data/lib/polars/slice.rb +1 -1
  180. data/lib/polars/sql_context.rb +13 -6
  181. data/lib/polars/string_cache.rb +19 -72
  182. data/lib/polars/string_expr.rb +561 -107
  183. data/lib/polars/string_name_space.rb +781 -109
  184. data/lib/polars/struct_expr.rb +139 -18
  185. data/lib/polars/struct_name_space.rb +19 -1
  186. data/lib/polars/testing.rb +24 -273
  187. data/lib/polars/utils/constants.rb +2 -0
  188. data/lib/polars/utils/construction/data_frame.rb +410 -0
  189. data/lib/polars/utils/construction/series.rb +350 -0
  190. data/lib/polars/utils/construction/utils.rb +9 -0
  191. data/lib/polars/utils/convert.rb +18 -8
  192. data/lib/polars/utils/deprecation.rb +11 -0
  193. data/lib/polars/utils/parse.rb +62 -9
  194. data/lib/polars/utils/reduce_balanced.rb +43 -0
  195. data/lib/polars/utils/serde.rb +22 -0
  196. data/lib/polars/utils/unstable.rb +19 -0
  197. data/lib/polars/utils/various.rb +86 -1
  198. data/lib/polars/utils.rb +63 -48
  199. data/lib/polars/version.rb +1 -1
  200. data/lib/polars.rb +85 -2
  201. metadata +80 -28
  202. data/ext/polars/src/allocator.rs +0 -13
  203. data/ext/polars/src/batched_csv.rs +0 -138
  204. data/ext/polars/src/functions/string_cache.rs +0 -25
  205. data/ext/polars/src/map/dataframe.rs +0 -338
  206. data/lib/polars/plot.rb +0 -109
@@ -2,28 +2,106 @@ module Polars
2
2
  module IO
3
3
  # Read into a DataFrame from a newline delimited JSON file.
4
4
  #
5
- # @param source [Object]
6
- # Path to a file or a file-like object.
5
+ # @param source [String]
6
+ # Path to a file.
7
+ # @param schema [Object]
8
+ # The DataFrame schema may be declared in several ways:
9
+ #
10
+ # * As a dict of \\\\{name:type} pairs; if type is nil, it will be auto-inferred.
11
+ # * As a list of column names; in this case types are automatically inferred.
12
+ # * As a list of (name,type) pairs; this is equivalent to the hash form.
13
+ #
14
+ # If you supply a list of column names that does not match the names in the
15
+ # underlying data, the names given here will overwrite them. The number
16
+ # of names given in the schema should match the underlying data dimensions.
17
+ # @param schema_overrides [Hash]
18
+ # Support type specification or override of one or more columns; note that
19
+ # any dtypes inferred from the schema param will be overridden.
20
+ # @param infer_schema_length [Integer]
21
+ # Infer the schema length from the first `infer_schema_length` rows.
22
+ # @param batch_size [Integer]
23
+ # Number of rows to read in each batch.
24
+ # @param n_rows [Integer]
25
+ # Stop reading from JSON file after reading `n_rows`.
26
+ # @param low_memory [Boolean]
27
+ # Reduce memory pressure at the expense of performance.
28
+ # @param rechunk [Boolean]
29
+ # Reallocate to contiguous memory when all chunks/ files are parsed.
30
+ # @param row_index_name [String]
31
+ # If not nil, this will insert a row count column with give name into the
32
+ # DataFrame.
33
+ # @param row_index_offset [Integer]
34
+ # Offset to start the row_count column (only use if the name is set).
35
+ # @param ignore_errors [Boolean]
36
+ # Return `Null` if parsing fails because of schema mismatches.
37
+ # @param storage_options [Hash]
38
+ # Options that indicate how to connect to a cloud provider.
39
+ #
40
+ # The cloud providers currently supported are AWS, GCP, and Azure.
41
+ # See supported keys here:
42
+ #
43
+ # * [aws](https://docs.rs/object_store/latest/object_store/aws/enum.AmazonS3ConfigKey.html)
44
+ # * [gcp](https://docs.rs/object_store/latest/object_store/gcp/enum.GoogleConfigKey.html)
45
+ # * [azure](https://docs.rs/object_store/latest/object_store/azure/enum.AzureConfigKey.html)
46
+ # * Hugging Face (`hf://`): Accepts an API key under the `token` parameter: \
47
+ # `{'token': '...'}`, or by setting the `HF_TOKEN` environment variable.
48
+ #
49
+ # If `storage_options` is not provided, Polars will try to infer the information
50
+ # from environment variables.
51
+ # @param credential_provider [Object]
52
+ # Provide a function that can be called to provide cloud storage
53
+ # credentials. The function is expected to return a hash of
54
+ # credential keys along with an optional credential expiry time.
55
+ # @param retries [Integer]
56
+ # Number of retries if accessing a cloud instance fails.
57
+ # @param file_cache_ttl [Integer]
58
+ # Amount of time to keep downloaded cloud files since their last access time,
59
+ # in seconds. Uses the `POLARS_FILE_CACHE_TTL` environment variable
60
+ # (which defaults to 1 hour) if not given.
61
+ # @param include_file_paths [String]
62
+ # Include the path of the source file(s) as a column with this name.
7
63
  #
8
64
  # @return [DataFrame]
9
65
  def read_ndjson(
10
66
  source,
11
67
  schema: nil,
12
68
  schema_overrides: nil,
13
- ignore_errors: false
69
+ infer_schema_length: N_INFER_DEFAULT,
70
+ batch_size: 1024,
71
+ n_rows: nil,
72
+ low_memory: false,
73
+ rechunk: false,
74
+ row_index_name: nil,
75
+ row_index_offset: 0,
76
+ ignore_errors: false,
77
+ storage_options: nil,
78
+ credential_provider: "auto",
79
+ retries: nil,
80
+ file_cache_ttl: nil,
81
+ include_file_paths: nil
14
82
  )
15
- if Utils.pathlike?(source)
16
- source = Utils.normalize_filepath(source)
17
- end
83
+ credential_provider_builder = _init_credential_provider_builder(
84
+ credential_provider, source, storage_options, "read_ndjson"
85
+ )
18
86
 
19
- rbdf =
20
- RbDataFrame.read_ndjson(
21
- source,
22
- ignore_errors,
23
- schema,
24
- schema_overrides
25
- )
26
- Utils.wrap_df(rbdf)
87
+ scan_ndjson(
88
+ source,
89
+ schema: schema,
90
+ schema_overrides: schema_overrides,
91
+ infer_schema_length: infer_schema_length,
92
+ batch_size: batch_size,
93
+ n_rows: n_rows,
94
+ low_memory: low_memory,
95
+ rechunk: rechunk,
96
+ row_index_name: row_index_name,
97
+ row_index_offset: row_index_offset,
98
+ ignore_errors: ignore_errors,
99
+ include_file_paths: include_file_paths,
100
+ retries: retries,
101
+ storage_options: storage_options,
102
+ credential_provider: credential_provider_builder,
103
+ file_cache_ttl: file_cache_ttl,
104
+ ).collect
27
105
  end
28
106
 
29
107
  # Lazily read from a newline delimited JSON file.
@@ -33,6 +111,19 @@ module Polars
33
111
  #
34
112
  # @param source [String]
35
113
  # Path to a file.
114
+ # @param schema [Object]
115
+ # The DataFrame schema may be declared in several ways:
116
+ #
117
+ # * As a dict of \\\\{name:type} pairs; if type is nil, it will be auto-inferred.
118
+ # * As a list of column names; in this case types are automatically inferred.
119
+ # * As a list of (name,type) pairs; this is equivalent to the hash form.
120
+ #
121
+ # If you supply a list of column names that does not match the names in the
122
+ # underlying data, the names given here will overwrite them. The number
123
+ # of names given in the schema should match the underlying data dimensions.
124
+ # @param schema_overrides [Hash]
125
+ # Support type specification or override of one or more columns; note that
126
+ # any dtypes inferred from the schema param will be overridden.
36
127
  # @param infer_schema_length [Integer]
37
128
  # Infer the schema length from the first `infer_schema_length` rows.
38
129
  # @param batch_size [Integer]
@@ -43,22 +134,58 @@ module Polars
43
134
  # Reduce memory pressure at the expense of performance.
44
135
  # @param rechunk [Boolean]
45
136
  # Reallocate to contiguous memory when all chunks/ files are parsed.
46
- # @param row_count_name [String]
137
+ # @param row_index_name [String]
47
138
  # If not nil, this will insert a row count column with give name into the
48
139
  # DataFrame.
49
- # @param row_count_offset [Integer]
140
+ # @param row_index_offset [Integer]
50
141
  # Offset to start the row_count column (only use if the name is set).
142
+ # @param ignore_errors [Boolean]
143
+ # Return `Null` if parsing fails because of schema mismatches.
144
+ # @param storage_options [Hash]
145
+ # Options that indicate how to connect to a cloud provider.
146
+ #
147
+ # The cloud providers currently supported are AWS, GCP, and Azure.
148
+ # See supported keys here:
149
+ #
150
+ # * [aws](https://docs.rs/object_store/latest/object_store/aws/enum.AmazonS3ConfigKey.html)
151
+ # * [gcp](https://docs.rs/object_store/latest/object_store/gcp/enum.GoogleConfigKey.html)
152
+ # * [azure](https://docs.rs/object_store/latest/object_store/azure/enum.AzureConfigKey.html)
153
+ # * Hugging Face (`hf://`): Accepts an API key under the `token` parameter: \
154
+ # `{'token': '...'}`, or by setting the `HF_TOKEN` environment variable.
155
+ #
156
+ # If `storage_options` is not provided, Polars will try to infer the information
157
+ # from environment variables.
158
+ # @param credential_provider [Object]
159
+ # Provide a function that can be called to provide cloud storage
160
+ # credentials. The function is expected to return a hash of
161
+ # credential keys along with an optional credential expiry time.
162
+ # @param retries [Integer]
163
+ # Number of retries if accessing a cloud instance fails.
164
+ # @param file_cache_ttl [Integer]
165
+ # Amount of time to keep downloaded cloud files since their last access time,
166
+ # in seconds. Uses the `POLARS_FILE_CACHE_TTL` environment variable
167
+ # (which defaults to 1 hour) if not given.
168
+ # @param include_file_paths [String]
169
+ # Include the path of the source file(s) as a column with this name.
51
170
  #
52
171
  # @return [LazyFrame]
53
172
  def scan_ndjson(
54
173
  source,
174
+ schema: nil,
175
+ schema_overrides: nil,
55
176
  infer_schema_length: N_INFER_DEFAULT,
56
177
  batch_size: 1024,
57
178
  n_rows: nil,
58
179
  low_memory: false,
59
- rechunk: true,
60
- row_count_name: nil,
61
- row_count_offset: 0
180
+ rechunk: false,
181
+ row_index_name: nil,
182
+ row_index_offset: 0,
183
+ ignore_errors: false,
184
+ storage_options: nil,
185
+ credential_provider: "auto",
186
+ retries: nil,
187
+ file_cache_ttl: nil,
188
+ include_file_paths: nil
62
189
  )
63
190
  sources = []
64
191
  if Utils.pathlike?(source)
@@ -73,16 +200,45 @@ module Polars
73
200
  source = nil
74
201
  end
75
202
 
203
+ if infer_schema_length == 0
204
+ msg = "'infer_schema_length' should be positive"
205
+ raise ArgumentError, msg
206
+ end
207
+
208
+ if !retries.nil?
209
+ msg = "the `retries` parameter was deprecated in 0.25.0; specify 'max_retries' in `storage_options` instead."
210
+ Utils.issue_deprecation_warning(msg)
211
+ storage_options = storage_options || {}
212
+ storage_options["max_retries"] = retries
213
+ end
214
+
215
+ if !file_cache_ttl.nil?
216
+ msg = "the `file_cache_ttl` parameter was deprecated in 0.25.0; specify 'file_cache_ttl' in `storage_options` instead."
217
+ Utils.issue_deprecation_warning(msg)
218
+ storage_options = storage_options || {}
219
+ storage_options["file_cache_ttl"] = file_cache_ttl
220
+ end
221
+
222
+ credential_provider_builder = _init_credential_provider_builder(
223
+ credential_provider, source, storage_options, "scan_ndjson"
224
+ )
225
+
76
226
  rblf =
77
227
  RbLazyFrame.new_from_ndjson(
78
228
  source,
79
229
  sources,
80
230
  infer_schema_length,
231
+ schema,
232
+ schema_overrides,
81
233
  batch_size,
82
234
  n_rows,
83
235
  low_memory,
84
236
  rechunk,
85
- Utils.parse_row_index_args(row_count_name, row_count_offset)
237
+ Utils.parse_row_index_args(row_index_name, row_index_offset),
238
+ ignore_errors,
239
+ include_file_paths,
240
+ storage_options,
241
+ credential_provider_builder
86
242
  )
87
243
  Utils.wrap_ldf(rblf)
88
244
  end
@@ -9,10 +9,10 @@ module Polars
9
9
  # of column names.
10
10
  # @param n_rows [Integer]
11
11
  # Stop reading from parquet file after reading `n_rows`.
12
- # @param row_count_name [String]
12
+ # @param row_index_name [String]
13
13
  # If not nil, this will insert a row count column with give name into the
14
14
  # DataFrame.
15
- # @param row_count_offset [Integer]
15
+ # @param row_index_offset [Integer]
16
16
  # Offset to start the row_count column (only use if the name is set).
17
17
  # @param parallel ["auto", "columns", "row_groups", "none"]
18
18
  # This determines the direction of parallelism. 'auto' will try to determine the
@@ -43,20 +43,32 @@ module Polars
43
43
  # Extra options that make sense for a particular storage connection.
44
44
  # @param credential_provider [Object]
45
45
  # Provide a function that can be called to provide cloud storage
46
- # credentials. The function is expected to return a dictionary of
46
+ # credentials. The function is expected to return a hash of
47
47
  # credential keys along with an optional credential expiry time.
48
48
  # @param retries [Integer]
49
49
  # Number of retries if accessing a cloud instance fails.
50
50
  # @param include_file_paths [String]
51
51
  # Include the path of the source file(s) as a column with this name.
52
+ # @param missing_columns ['insert', 'raise']
53
+ # Configuration for behavior when columns defined in the schema
54
+ # are missing from the data:
55
+ #
56
+ # * `insert`: Inserts the missing columns using NULLs as the row values.
57
+ # * `raise`: Raises an error.
58
+ # @param allow_missing_columns [Boolean]
59
+ # When reading a list of parquet files, if a column existing in the first
60
+ # file cannot be found in subsequent files, the default behavior is to
61
+ # raise an error. However, if `allow_missing_columns` is set to
62
+ # `true`, a full-NULL column is returned instead of erroring for the files
63
+ # that do not contain the column.
52
64
  #
53
65
  # @return [DataFrame]
54
66
  def read_parquet(
55
67
  source,
56
68
  columns: nil,
57
69
  n_rows: nil,
58
- row_count_name: nil,
59
- row_count_offset: 0,
70
+ row_index_name: nil,
71
+ row_index_offset: 0,
60
72
  parallel: "auto",
61
73
  use_statistics: true,
62
74
  hive_partitioning: nil,
@@ -67,17 +79,18 @@ module Polars
67
79
  rechunk: false,
68
80
  low_memory: false,
69
81
  storage_options: nil,
70
- credential_provider: nil,
71
- retries: 2,
82
+ credential_provider: "auto",
83
+ retries: nil,
72
84
  include_file_paths: nil,
73
- allow_missing_columns: false
85
+ missing_columns: "raise",
86
+ allow_missing_columns: nil
74
87
  )
75
88
  lf =
76
89
  scan_parquet(
77
90
  source,
78
91
  n_rows: n_rows,
79
- row_count_name: row_count_name,
80
- row_count_offset: row_count_offset,
92
+ row_index_name: row_index_name,
93
+ row_index_offset: row_index_offset,
81
94
  parallel: parallel,
82
95
  use_statistics: use_statistics,
83
96
  hive_partitioning: hive_partitioning,
@@ -92,6 +105,7 @@ module Polars
92
105
  retries: retries,
93
106
  glob: glob,
94
107
  include_file_paths: include_file_paths,
108
+ missing_columns: missing_columns,
95
109
  allow_missing_columns: allow_missing_columns
96
110
  )
97
111
 
@@ -111,13 +125,59 @@ module Polars
111
125
  # @param source [Object]
112
126
  # Path to a file or a file-like object.
113
127
  #
114
- # @return [Hash]
128
+ # @return [Schema]
115
129
  def read_parquet_schema(source)
116
130
  if Utils.pathlike?(source)
117
131
  source = Utils.normalize_filepath(source)
118
132
  end
119
133
 
120
- Plr.parquet_schema(source)
134
+ scan_parquet(source).collect_schema
135
+ end
136
+
137
+ # Get file-level custom metadata of a Parquet file without reading data.
138
+ #
139
+ # @note
140
+ # This functionality is considered **experimental**. It may be removed or
141
+ # changed at any point without it being considered a breaking change.
142
+ #
143
+ # @param source [Object]
144
+ # Path to a file or a file-like object.
145
+ # @param storage_options [Hash]
146
+ # Extra options that make sense for a particular storage connection.
147
+ # @param credential_provider [Object]
148
+ # Provide a function that can be called to provide cloud storage
149
+ # credentials. The function is expected to return a hash of
150
+ # credential keys along with an optional credential expiry time.
151
+ # @param retries [Integer]
152
+ # Number of retries if accessing a cloud instance fails.
153
+ #
154
+ # @return [Hash]
155
+ def read_parquet_metadata(
156
+ source,
157
+ storage_options: nil,
158
+ credential_provider: "auto",
159
+ retries: nil
160
+ )
161
+ if Utils.pathlike?(source)
162
+ source = Utils.normalize_filepath(source, check_not_directory: false)
163
+ end
164
+
165
+ if !retries.nil?
166
+ msg = "the `retries` parameter was deprecated in 0.25.0; specify 'max_retries' in `storage_options` instead."
167
+ Utils.issue_deprecation_warning(msg)
168
+ storage_options = storage_options || {}
169
+ storage_options["max_retries"] = retries
170
+ end
171
+
172
+ credential_provider_builder = _init_credential_provider_builder(
173
+ credential_provider, source, storage_options, "scan_parquet"
174
+ )
175
+
176
+ Plr.read_parquet_metadata(
177
+ source,
178
+ storage_options,
179
+ credential_provider_builder
180
+ )
121
181
  end
122
182
 
123
183
  # Lazily read from a parquet file or multiple files via glob patterns.
@@ -129,10 +189,10 @@ module Polars
129
189
  # Path to a file or a file-like object.
130
190
  # @param n_rows [Integer]
131
191
  # Stop reading from parquet file after reading `n_rows`.
132
- # @param row_count_name [String]
192
+ # @param row_index_name [String]
133
193
  # If not nil, this will insert a row count column with give name into the
134
194
  # DataFrame.
135
- # @param row_count_offset [Integer]
195
+ # @param row_index_offset [Integer]
136
196
  # Offset to start the row_count column (only use if the name is set).
137
197
  # @param parallel ["auto", "columns", "row_groups", "none"]
138
198
  # This determines the direction of parallelism. 'auto' will try to determine the
@@ -145,6 +205,8 @@ module Polars
145
205
  # to prune reads.
146
206
  # @param glob [Boolean]
147
207
  # Expand path given via globbing rules.
208
+ # @param hidden_file_prefix [Boolean]
209
+ # Skip reading files whose names begin with the specified prefixes.
148
210
  # @param schema [Object]
149
211
  # Specify the datatypes of the columns. The datatypes must match the
150
212
  # datatypes in the file(s). If there are extra columns that are not in the
@@ -165,23 +227,44 @@ module Polars
165
227
  # Extra options that make sense for a particular storage connection.
166
228
  # @param credential_provider [Object]
167
229
  # Provide a function that can be called to provide cloud storage
168
- # credentials. The function is expected to return a dictionary of
230
+ # credentials. The function is expected to return a hash of
169
231
  # credential keys along with an optional credential expiry time.
170
232
  # @param retries [Integer]
171
233
  # Number of retries if accessing a cloud instance fails.
172
234
  # @param include_file_paths [String]
173
235
  # Include the path of the source file(s) as a column with this name.
236
+ # @param missing_columns ['insert', 'raise']
237
+ # Configuration for behavior when columns defined in the schema
238
+ # are missing from the data:
239
+ #
240
+ # * `insert`: Inserts the missing columns using NULLs as the row values.
241
+ # * `raise`: Raises an error.
242
+ # @param allow_missing_columns [Boolean]
243
+ # When reading a list of parquet files, if a column existing in the first
244
+ # file cannot be found in subsequent files, the default behavior is to
245
+ # raise an error. However, if `allow_missing_columns` is set to
246
+ # `true`, a full-NULL column is returned instead of erroring for the files
247
+ # that do not contain the column.
248
+ # @param extra_columns ['ignore', 'raise']
249
+ # Configuration for behavior when extra columns outside of the
250
+ # defined schema are encountered in the data:
251
+ # * `ignore`: Silently ignores.
252
+ # * `raise`: Raises an error.
253
+ # @param cast_options [Object]
254
+ # Configuration for column type-casting during scans. Useful for datasets
255
+ # containing files that have differing schemas.
174
256
  #
175
257
  # @return [LazyFrame]
176
258
  def scan_parquet(
177
259
  source,
178
260
  n_rows: nil,
179
- row_count_name: nil,
180
- row_count_offset: 0,
261
+ row_index_name: nil,
262
+ row_index_offset: 0,
181
263
  parallel: "auto",
182
264
  use_statistics: true,
183
265
  hive_partitioning: nil,
184
266
  glob: true,
267
+ hidden_file_prefix: nil,
185
268
  schema: nil,
186
269
  hive_schema: nil,
187
270
  try_parse_hive_dates: true,
@@ -189,100 +272,95 @@ module Polars
189
272
  low_memory: false,
190
273
  cache: true,
191
274
  storage_options: nil,
192
- credential_provider: nil,
193
- retries: 2,
275
+ credential_provider: "auto",
276
+ retries: nil,
194
277
  include_file_paths: nil,
195
- allow_missing_columns: false
278
+ missing_columns: "raise",
279
+ allow_missing_columns: nil,
280
+ extra_columns: "raise",
281
+ cast_options: nil,
282
+ _column_mapping: nil,
283
+ _default_values: nil,
284
+ _deletion_files: nil,
285
+ _table_statistics: nil,
286
+ _row_count: nil
196
287
  )
197
- if Utils.pathlike?(source)
198
- source = Utils.normalize_filepath(source, check_not_directory: false)
199
- elsif Utils.is_path_or_str_sequence(source)
200
- source = source.map { |s| Utils.normalize_filepath(s, check_not_directory: false) }
288
+ if !schema.nil?
289
+ msg = "the `schema` parameter of `scan_parquet` is considered unstable."
290
+ Utils.issue_unstable_warning(msg)
201
291
  end
202
292
 
203
- if credential_provider
204
- raise Todo
293
+ if !hive_schema.nil?
294
+ msg = "the `hive_schema` parameter of `scan_parquet` is considered unstable."
295
+ Utils.issue_unstable_warning(msg)
205
296
  end
206
297
 
207
- _scan_parquet_impl(
208
- source,
209
- n_rows: n_rows,
210
- cache: cache,
211
- parallel: parallel,
212
- rechunk: rechunk,
213
- row_index_name: row_count_name,
214
- row_index_offset: row_count_offset,
215
- storage_options: storage_options,
216
- credential_provider: credential_provider,
217
- low_memory: low_memory,
218
- use_statistics: use_statistics,
219
- hive_partitioning: hive_partitioning,
220
- schema: schema,
221
- hive_schema: hive_schema,
222
- try_parse_hive_dates: try_parse_hive_dates,
223
- retries: retries,
224
- glob: glob,
225
- include_file_paths: include_file_paths,
226
- allow_missing_columns: allow_missing_columns
227
- )
228
- end
298
+ if !cast_options.nil?
299
+ msg = "The `cast_options` parameter of `scan_parquet` is considered unstable."
300
+ Utils.issue_unstable_warning(msg)
301
+ end
229
302
 
230
- # @private
231
- def _scan_parquet_impl(
232
- source,
233
- n_rows: nil,
234
- cache: true,
235
- parallel: "auto",
236
- rechunk: true,
237
- row_index_name: nil,
238
- row_index_offset: 0,
239
- storage_options: nil,
240
- credential_provider: nil,
241
- low_memory: false,
242
- use_statistics: true,
243
- hive_partitioning: nil,
244
- glob: true,
245
- schema: nil,
246
- hive_schema: nil,
247
- try_parse_hive_dates: true,
248
- retries: 2,
249
- include_file_paths: nil,
250
- allow_missing_columns: false
251
- )
252
- if source.is_a?(::Array)
253
- sources = source
254
- source = nil
255
- else
256
- sources = []
303
+ if !hidden_file_prefix.nil?
304
+ msg = "The `hidden_file_prefix` parameter of `scan_parquet` is considered unstable."
305
+ Utils.issue_unstable_warning(msg)
257
306
  end
258
307
 
259
- if storage_options
260
- storage_options = storage_options.map { |k, v| [k.to_s, v.to_s] }
261
- else
262
- storage_options = nil
308
+ if !allow_missing_columns.nil?
309
+ Utils.issue_deprecation_warning(
310
+ "the parameter `allow_missing_columns` for `scan_parquet` is deprecated. " +
311
+ "Use the parameter `missing_columns` instead and pass one of " +
312
+ "`('insert', 'raise')`."
313
+ )
314
+
315
+ missing_columns = allow_missing_columns ? "insert" : "raise"
263
316
  end
264
317
 
318
+ if !retries.nil?
319
+ msg = "the `retries` parameter was deprecated in 0.25.0; specify 'max_retries' in `storage_options` instead."
320
+ Utils.issue_deprecation_warning(msg)
321
+ storage_options = storage_options || {}
322
+ storage_options["max_retries"] = retries
323
+ end
324
+
325
+ sources = get_sources(source)
326
+
327
+ credential_provider_builder =
328
+ _init_credential_provider_builder(
329
+ credential_provider,
330
+ sources,
331
+ storage_options,
332
+ "scan_parquet"
333
+ )
334
+
265
335
  rblf =
266
336
  RbLazyFrame.new_from_parquet(
267
- source,
268
337
  sources,
269
- n_rows,
270
- cache,
338
+ schema,
339
+ ScanOptions.new(
340
+ row_index: !row_index_name.nil? ? [row_index_name, row_index_offset] : nil,
341
+ pre_slice: !n_rows.nil? ? [0, n_rows] : nil,
342
+ cast_options: cast_options,
343
+ extra_columns: extra_columns,
344
+ missing_columns: missing_columns,
345
+ include_file_paths: include_file_paths,
346
+ glob: glob,
347
+ hidden_file_prefix: hidden_file_prefix.is_a?(::String) ? [hidden_file_prefix] : hidden_file_prefix,
348
+ hive_partitioning: hive_partitioning,
349
+ hive_schema: hive_schema,
350
+ try_parse_hive_dates: try_parse_hive_dates,
351
+ rechunk: rechunk,
352
+ cache: cache,
353
+ storage_options: storage_options,
354
+ credential_provider: credential_provider_builder,
355
+ column_mapping: _column_mapping,
356
+ default_values: _default_values,
357
+ deletion_files: _deletion_files,
358
+ table_statistics: _table_statistics,
359
+ row_count: _row_count
360
+ ),
271
361
  parallel,
272
- rechunk,
273
- Utils.parse_row_index_args(row_index_name, row_index_offset),
274
362
  low_memory,
275
- storage_options,
276
- credential_provider,
277
- use_statistics,
278
- hive_partitioning,
279
- schema,
280
- hive_schema,
281
- try_parse_hive_dates,
282
- retries,
283
- glob,
284
- include_file_paths,
285
- allow_missing_columns
363
+ use_statistics
286
364
  )
287
365
  Utils.wrap_ldf(rblf)
288
366
  end
@@ -0,0 +1,55 @@
1
+ module Polars
2
+ module IO
3
+ # @private
4
+ class ScanOptions
5
+ attr_reader :row_index, :pre_slice, :cast_options, :extra_columns, :missing_columns,
6
+ :include_file_paths, :glob, :hidden_file_prefix, :hive_partitioning, :hive_schema, :try_parse_hive_dates,
7
+ :rechunk, :cache, :storage_options, :credential_provider, :retries, :column_mapping,
8
+ :default_values, :deletion_files, :table_statistics, :row_count
9
+
10
+ def initialize(
11
+ row_index: nil,
12
+ pre_slice: nil,
13
+ cast_options: nil,
14
+ extra_columns: "raise",
15
+ missing_columns: "raise",
16
+ include_file_paths: nil,
17
+ glob: true,
18
+ hidden_file_prefix: nil,
19
+ hive_partitioning: nil,
20
+ hive_schema: nil,
21
+ try_parse_hive_dates: true,
22
+ rechunk: false,
23
+ cache: true,
24
+ storage_options: nil,
25
+ credential_provider: nil,
26
+ column_mapping: nil,
27
+ default_values: nil,
28
+ deletion_files: nil,
29
+ table_statistics: nil,
30
+ row_count: nil
31
+ )
32
+ @row_index = row_index
33
+ @pre_slice = pre_slice
34
+ @cast_options = cast_options
35
+ @extra_columns = extra_columns
36
+ @missing_columns = missing_columns
37
+ @include_file_paths = include_file_paths
38
+ @glob = glob
39
+ @hidden_file_prefix = hidden_file_prefix
40
+ @hive_partitioning = hive_partitioning
41
+ @hive_schema = hive_schema
42
+ @try_parse_hive_dates = try_parse_hive_dates
43
+ @rechunk = rechunk
44
+ @cache = cache
45
+ @storage_options = storage_options
46
+ @credential_provider = credential_provider
47
+ @column_mapping = column_mapping
48
+ @default_values = default_values
49
+ @deletion_files = deletion_files
50
+ @table_statistics = table_statistics
51
+ @row_count = row_count
52
+ end
53
+ end
54
+ end
55
+ end