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
data/lib/polars/io/csv.rb CHANGED
@@ -16,38 +16,55 @@ module Polars
16
16
  # Rename columns right after parsing the CSV file. If the given
17
17
  # list is shorter than the width of the DataFrame the remaining
18
18
  # columns will have their original name.
19
- # @param sep [String]
20
- # Single byte character to use as delimiter in the file.
21
- # @param comment_char [String]
22
- # Single byte character that indicates the start of a comment line,
23
- # for instance `#`.
19
+ # @param separator [String]
20
+ # Single byte character to use as separator in the file.
21
+ # @param comment_prefix [String]
22
+ # A string used to indicate the start of a comment line. Comment lines are skipped
23
+ # during parsing. Common examples of comment prefixes are `#` and `//`.
24
24
  # @param quote_char [String]
25
25
  # Single byte character used for csv quoting.
26
26
  # Set to nil to turn off special handling and escaping of quotes.
27
27
  # @param skip_rows [Integer]
28
28
  # Start reading after `skip_rows` lines.
29
- # @param dtypes [Object]
30
- # Overwrite dtypes during inference.
29
+ # @param skip_lines [Integer]
30
+ # Start reading after `skip_lines` lines. The header will be parsed at this
31
+ # offset. Note that CSV escaping will not be respected when skipping lines.
32
+ # If you want to skip valid CSV rows, use `skip_rows`.
33
+ # @param schema [Object]
34
+ # Provide the schema. This means that polars doesn't do schema inference.
35
+ # This argument expects the complete schema, whereas `schema_overrides` can be
36
+ # used to partially overwrite a schema. Note that the order of the columns in
37
+ # the provided `schema` must match the order of the columns in the CSV being read.
38
+ # @param schema_overrides [Object]
39
+ # Overwrite dtypes for specific or all columns during schema inference.
31
40
  # @param null_values [Object]
32
41
  # Values to interpret as null values. You can provide a:
33
42
  #
34
43
  # - `String`: All values equal to this string will be null.
35
44
  # - `Array`: All values equal to any string in this array will be null.
36
45
  # - `Hash`: A hash that maps column name to a null value string.
46
+ # @param missing_utf8_is_empty_string [Boolean]
47
+ # By default a missing value is considered to be null; if you would prefer missing
48
+ # utf8 values to be treated as the empty string you can set this param true.
37
49
  # @param ignore_errors [Boolean]
38
50
  # Try to keep reading lines if some lines yield errors.
39
51
  # First try `infer_schema_length: 0` to read all columns as
40
52
  # `:str` to check which values might cause an issue.
41
- # @param parse_dates [Boolean]
53
+ # @param try_parse_dates [Boolean]
42
54
  # Try to automatically parse dates. If this does not succeed,
43
55
  # the column remains of data type `:str`.
44
56
  # @param n_threads [Integer]
45
57
  # Number of threads to use in csv parsing.
46
58
  # Defaults to the number of physical cpu's of your system.
59
+ # @param infer_schema [Boolean]
60
+ # When `true`, the schema is inferred from the data using the first
61
+ # `infer_schema_length` rows.
62
+ # When `false`, the schema is not inferred and will be `Polars::String` if not
63
+ # specified in `schema` or `schema_overrides`.
47
64
  # @param infer_schema_length [Integer]
48
- # Maximum number of lines to read to infer schema.
49
- # If set to 0, all columns will be read as `:utf8`.
50
- # If set to `nil`, a full table scan will be done (slow).
65
+ # The maximum number of rows to scan for schema inference.
66
+ # If set to `nil`, the full data may be scanned *(this is slow)*.
67
+ # Set `infer_schema: false` to read all columns as `Polars::String`.
51
68
  # @param batch_size [Integer]
52
69
  # Number of lines to read into the buffer at once.
53
70
  # Modify this to change performance.
@@ -70,15 +87,22 @@ module Polars
70
87
  # particular storage connection.
71
88
  # @param skip_rows_after_header [Integer]
72
89
  # Skip this number of rows when the header is parsed.
73
- # @param row_count_name [String]
90
+ # @param row_index_name [String]
74
91
  # If not nil, this will insert a row count column with the given name into
75
92
  # the DataFrame.
76
- # @param row_count_offset [Integer]
93
+ # @param row_index_offset [Integer]
77
94
  # Offset to start the row_count column (only used if the name is set).
78
95
  # @param eol_char [String]
79
96
  # Single byte end of line character.
97
+ # @param raise_if_empty [Boolean]
98
+ # When there is no data in the source, `NoDataError` is raised. If this parameter
99
+ # is set to false, an empty DataFrame (with no columns) is returned instead.
80
100
  # @param truncate_ragged_lines [Boolean]
81
101
  # Truncate lines that are longer than the schema.
102
+ # @param decimal_comma [Boolean]
103
+ # Parse floats using a comma as the decimal separator instead of a period.
104
+ # @param glob [Boolean]
105
+ # Expand path given via globbing rules.
82
106
  #
83
107
  # @return [DataFrame]
84
108
  #
@@ -92,30 +116,36 @@ module Polars
92
116
  has_header: true,
93
117
  columns: nil,
94
118
  new_columns: nil,
95
- sep: ",",
96
- comment_char: nil,
119
+ separator: ",",
120
+ comment_prefix: nil,
97
121
  quote_char: '"',
98
122
  skip_rows: 0,
99
- dtypes: nil,
123
+ skip_lines: 0,
124
+ schema: nil,
125
+ schema_overrides: nil,
100
126
  null_values: nil,
127
+ missing_utf8_is_empty_string: false,
101
128
  ignore_errors: false,
102
- parse_dates: false,
129
+ try_parse_dates: false,
103
130
  n_threads: nil,
131
+ infer_schema: true,
104
132
  infer_schema_length: N_INFER_DEFAULT,
105
133
  batch_size: 8192,
106
134
  n_rows: nil,
107
135
  encoding: "utf8",
108
136
  low_memory: false,
109
- rechunk: true,
137
+ rechunk: false,
110
138
  storage_options: nil,
111
139
  skip_rows_after_header: 0,
112
- row_count_name: nil,
113
- row_count_offset: 0,
140
+ row_index_name: nil,
141
+ row_index_offset: 0,
114
142
  eol_char: "\n",
115
- truncate_ragged_lines: false
143
+ raise_if_empty: true,
144
+ truncate_ragged_lines: false,
145
+ decimal_comma: false,
146
+ glob: true
116
147
  )
117
- Utils._check_arg_is_1byte("sep", sep, false)
118
- Utils._check_arg_is_1byte("comment_char", comment_char, false)
148
+ Utils._check_arg_is_1byte("separator", separator, false)
119
149
  Utils._check_arg_is_1byte("quote_char", quote_char, true)
120
150
  Utils._check_arg_is_1byte("eol_char", eol_char, false)
121
151
 
@@ -131,8 +161,8 @@ module Polars
131
161
  end
132
162
  end
133
163
 
134
- if projection || new_columns
135
- raise Todo
164
+ if !infer_schema
165
+ infer_schema_length = 0
136
166
  end
137
167
 
138
168
  df = nil
@@ -141,14 +171,17 @@ module Polars
141
171
  data,
142
172
  has_header: has_header,
143
173
  columns: columns || projection,
144
- sep: sep,
145
- comment_char: comment_char,
174
+ separator: separator,
175
+ comment_prefix: comment_prefix,
146
176
  quote_char: quote_char,
147
177
  skip_rows: skip_rows,
148
- dtypes: dtypes,
178
+ skip_lines: skip_lines,
179
+ schema_overrides: schema_overrides,
180
+ schema: schema,
149
181
  null_values: null_values,
182
+ missing_utf8_is_empty_string: missing_utf8_is_empty_string,
150
183
  ignore_errors: ignore_errors,
151
- parse_dates: parse_dates,
184
+ try_parse_dates: try_parse_dates,
152
185
  n_threads: n_threads,
153
186
  infer_schema_length: infer_schema_length,
154
187
  batch_size: batch_size,
@@ -157,10 +190,13 @@ module Polars
157
190
  low_memory: low_memory,
158
191
  rechunk: rechunk,
159
192
  skip_rows_after_header: skip_rows_after_header,
160
- row_count_name: row_count_name,
161
- row_count_offset: row_count_offset,
193
+ row_index_name: row_index_name,
194
+ row_index_offset: row_index_offset,
162
195
  eol_char: eol_char,
163
- truncate_ragged_lines: truncate_ragged_lines
196
+ raise_if_empty: raise_if_empty,
197
+ truncate_ragged_lines: truncate_ragged_lines,
198
+ decimal_comma: decimal_comma,
199
+ glob: glob
164
200
  )
165
201
  end
166
202
 
@@ -176,26 +212,27 @@ module Polars
176
212
  file,
177
213
  has_header: true,
178
214
  columns: nil,
179
- sep: ",",
180
- comment_char: nil,
215
+ separator: ",",
216
+ comment_prefix: nil,
181
217
  quote_char: '"',
182
218
  skip_rows: 0,
183
- dtypes: nil,
219
+ skip_lines: 0,
184
220
  schema: nil,
221
+ schema_overrides: nil,
185
222
  null_values: nil,
186
223
  missing_utf8_is_empty_string: false,
187
224
  ignore_errors: false,
188
- parse_dates: false,
225
+ try_parse_dates: false,
189
226
  n_threads: nil,
190
227
  infer_schema_length: N_INFER_DEFAULT,
191
228
  batch_size: 8192,
192
229
  n_rows: nil,
193
230
  encoding: "utf8",
194
231
  low_memory: false,
195
- rechunk: true,
232
+ rechunk: false,
196
233
  skip_rows_after_header: 0,
197
- row_count_name: nil,
198
- row_count_offset: 0,
234
+ row_index_name: nil,
235
+ row_index_offset: 0,
199
236
  eol_char: "\n",
200
237
  raise_if_empty: true,
201
238
  truncate_ragged_lines: false,
@@ -213,16 +250,16 @@ module Polars
213
250
 
214
251
  dtype_list = nil
215
252
  dtype_slice = nil
216
- if !dtypes.nil?
217
- if dtypes.is_a?(Hash)
253
+ if !schema_overrides.nil?
254
+ if schema_overrides.is_a?(Hash)
218
255
  dtype_list = []
219
- dtypes.each do |k, v|
220
- dtype_list << [k, Utils.rb_type_to_dtype(v)]
256
+ schema_overrides.each do |k, v|
257
+ dtype_list << [k, Utils.parse_into_dtype(v)]
221
258
  end
222
- elsif dtypes.is_a?(::Array)
223
- dtype_slice = dtypes
259
+ elsif schema_overrides.is_a?(::Array)
260
+ dtype_slice = schema_overrides
224
261
  else
225
- raise ArgumentError, "dtype arg should be list or dict"
262
+ raise TypeError, "dtype arg should be array or hash"
226
263
  end
227
264
  end
228
265
 
@@ -242,11 +279,13 @@ module Polars
242
279
  scan = scan_csv(
243
280
  file,
244
281
  has_header: has_header,
245
- sep: sep,
246
- comment_char: comment_char,
282
+ separator: separator,
283
+ comment_prefix: comment_prefix,
247
284
  quote_char: quote_char,
248
285
  skip_rows: skip_rows,
249
- dtypes: dtypes_dict,
286
+ skip_lines: skip_lines,
287
+ schema: schema,
288
+ schema_overrides: dtypes_dict,
250
289
  null_values: null_values,
251
290
  missing_utf8_is_empty_string: missing_utf8_is_empty_string,
252
291
  ignore_errors: ignore_errors,
@@ -255,9 +294,10 @@ module Polars
255
294
  low_memory: low_memory,
256
295
  rechunk: rechunk,
257
296
  skip_rows_after_header: skip_rows_after_header,
258
- row_count_name: row_count_name,
259
- row_count_offset: row_count_offset,
297
+ row_index_name: row_index_name,
298
+ row_index_offset: row_index_offset,
260
299
  eol_char: eol_char,
300
+ raise_if_empty: raise_if_empty,
261
301
  truncate_ragged_lines: truncate_ragged_lines,
262
302
  decimal_comma: decimal_comma,
263
303
  glob: glob
@@ -282,8 +322,9 @@ module Polars
282
322
  ignore_errors,
283
323
  n_rows,
284
324
  skip_rows,
325
+ skip_lines,
285
326
  projection,
286
- sep,
327
+ separator,
287
328
  rechunk,
288
329
  columns,
289
330
  encoding,
@@ -292,13 +333,13 @@ module Polars
292
333
  dtype_list,
293
334
  dtype_slice,
294
335
  low_memory,
295
- comment_char,
336
+ comment_prefix,
296
337
  quote_char,
297
338
  processed_null_values,
298
339
  missing_utf8_is_empty_string,
299
- parse_dates,
340
+ try_parse_dates,
300
341
  skip_rows_after_header,
301
- Utils.parse_row_index_args(row_count_name, row_count_offset),
342
+ Utils.parse_row_index_args(row_index_name, row_index_offset),
302
343
  eol_char,
303
344
  raise_if_empty,
304
345
  truncate_ragged_lines,
@@ -315,11 +356,14 @@ module Polars
315
356
  # file chunks. After that work will only be done
316
357
  # if `next_batches` is called.
317
358
  #
359
+ # @deprecated
360
+ # Use `scan_csv().collect_batches` instead.
361
+ #
318
362
  # @param source [Object]
319
363
  # Path to a file or a file-like object.
320
364
  # @param has_header [Boolean]
321
365
  # Indicate if the first row of dataset is a header or not.
322
- # If set to False, column names will be autogenerated in the
366
+ # If set to false, column names will be autogenerated in the
323
367
  # following format: `column_x`, with `x` being an
324
368
  # enumeration over every column in the dataset starting at 1.
325
369
  # @param columns [Object]
@@ -329,17 +373,21 @@ module Polars
329
373
  # Rename columns right after parsing the CSV file. If the given
330
374
  # list is shorter than the width of the DataFrame the remaining
331
375
  # columns will have their original name.
332
- # @param sep [String]
333
- # Single byte character to use as delimiter in the file.
334
- # @param comment_char [String]
335
- # Single byte character that indicates the start of a comment line,
336
- # for instance `#`.
376
+ # @param separator [String]
377
+ # Single byte character to use as separator in the file.
378
+ # @param comment_prefix [String]
379
+ # A string used to indicate the start of a comment line. Comment lines are skipped
380
+ # during parsing. Common examples of comment prefixes are `#` and `//`.
337
381
  # @param quote_char [String]
338
382
  # Single byte character used for csv quoting, default = `"`.
339
383
  # Set to nil to turn off special handling and escaping of quotes.
340
384
  # @param skip_rows [Integer]
341
385
  # Start reading after `skip_rows` lines.
342
- # @param dtypes [Object]
386
+ # @param skip_lines [Integer]
387
+ # Start reading after `skip_lines` lines. The header will be parsed at this
388
+ # offset. Note that CSV escaping will not be respected when skipping lines.
389
+ # If you want to skip valid CSV rows, use `skip_rows`.
390
+ # @param schema_overrides [Object]
343
391
  # Overwrite dtypes during inference.
344
392
  # @param null_values [Object]
345
393
  # Values to interpret as null values. You can provide a:
@@ -347,11 +395,14 @@ module Polars
347
395
  # - `String`: All values equal to this string will be null.
348
396
  # - `Array`: All values equal to any string in this array will be null.
349
397
  # - `Hash`: A hash that maps column name to a null value string.
398
+ # @param missing_utf8_is_empty_string [Boolean]
399
+ # By default a missing value is considered to be null; if you would prefer missing
400
+ # utf8 values to be treated as the empty string you can set this param true.
350
401
  # @param ignore_errors [Boolean]
351
402
  # Try to keep reading lines if some lines yield errors.
352
403
  # First try `infer_schema_length: 0` to read all columns as
353
404
  # `:str` to check which values might cause an issue.
354
- # @param parse_dates [Boolean]
405
+ # @param try_parse_dates [Boolean]
355
406
  # Try to automatically parse dates. If this does not succeed,
356
407
  # the column remains of data type `:str`.
357
408
  # @param n_threads [Integer]
@@ -380,21 +431,26 @@ module Polars
380
431
  # aggregating the chunks into a single array.
381
432
  # @param skip_rows_after_header [Integer]
382
433
  # Skip this number of rows when the header is parsed.
383
- # @param row_count_name [String]
434
+ # @param row_index_name [String]
384
435
  # If not nil, this will insert a row count column with the given name into
385
436
  # the DataFrame.
386
- # @param row_count_offset [Integer]
437
+ # @param row_index_offset [Integer]
387
438
  # Offset to start the row_count column (only used if the name is set).
388
439
  # @param eol_char [String]
389
440
  # Single byte end of line character.
441
+ # @param raise_if_empty [Boolean]
442
+ # When there is no data in the source,`NoDataError` is raised. If this parameter
443
+ # is set to false, `nil` will be returned from `next_batches(n)` instead.
390
444
  # @param truncate_ragged_lines [Boolean]
391
445
  # Truncate lines that are longer than the schema.
446
+ # @param decimal_comma [Boolean]
447
+ # Parse floats using a comma as the decimal separator instead of a period.
392
448
  #
393
449
  # @return [BatchedCsvReader]
394
450
  #
395
451
  # @example
396
452
  # reader = Polars.read_csv_batched(
397
- # "./tpch/tables_scale_100/lineitem.tbl", sep: "|", parse_dates: true
453
+ # "./tpch/tables_scale_100/lineitem.tbl", separator: "|", try_parse_dates: true
398
454
  # )
399
455
  # reader.next_batches(5)
400
456
  def read_csv_batched(
@@ -402,25 +458,26 @@ module Polars
402
458
  has_header: true,
403
459
  columns: nil,
404
460
  new_columns: nil,
405
- sep: ",",
406
- comment_char: nil,
461
+ separator: ",",
462
+ comment_prefix: nil,
407
463
  quote_char: '"',
408
464
  skip_rows: 0,
409
- dtypes: nil,
465
+ skip_lines: 0,
466
+ schema_overrides: nil,
410
467
  null_values: nil,
411
468
  missing_utf8_is_empty_string: false,
412
469
  ignore_errors: false,
413
- parse_dates: false,
470
+ try_parse_dates: false,
414
471
  n_threads: nil,
415
472
  infer_schema_length: N_INFER_DEFAULT,
416
473
  batch_size: 50_000,
417
474
  n_rows: nil,
418
475
  encoding: "utf8",
419
476
  low_memory: false,
420
- rechunk: true,
477
+ rechunk: false,
421
478
  skip_rows_after_header: 0,
422
- row_count_name: nil,
423
- row_count_offset: 0,
479
+ row_index_name: nil,
480
+ row_index_offset: 0,
424
481
  eol_char: "\n",
425
482
  raise_if_empty: true,
426
483
  truncate_ragged_lines: false,
@@ -436,23 +493,20 @@ module Polars
436
493
  end
437
494
  end
438
495
 
439
- if projection || new_columns
440
- raise Todo
441
- end
442
-
443
496
  BatchedCsvReader.new(
444
497
  source,
445
498
  has_header: has_header,
446
499
  columns: columns || projection,
447
- sep: sep,
448
- comment_char: comment_char,
500
+ separator: separator,
501
+ comment_prefix: comment_prefix,
449
502
  quote_char: quote_char,
450
503
  skip_rows: skip_rows,
451
- dtypes: dtypes,
504
+ skip_lines: skip_lines,
505
+ schema_overrides: schema_overrides,
452
506
  null_values: null_values,
453
507
  missing_utf8_is_empty_string: missing_utf8_is_empty_string,
454
508
  ignore_errors: ignore_errors,
455
- parse_dates: parse_dates,
509
+ try_parse_dates: try_parse_dates,
456
510
  n_threads: n_threads,
457
511
  infer_schema_length: infer_schema_length,
458
512
  batch_size: batch_size,
@@ -461,8 +515,8 @@ module Polars
461
515
  low_memory: low_memory,
462
516
  rechunk: rechunk,
463
517
  skip_rows_after_header: skip_rows_after_header,
464
- row_count_name: row_count_name,
465
- row_count_offset: row_count_offset,
518
+ row_index_name: row_index_name,
519
+ row_index_offset: row_index_offset,
466
520
  eol_char: eol_char,
467
521
  new_columns: new_columns,
468
522
  raise_if_empty: raise_if_empty,
@@ -484,25 +538,37 @@ module Polars
484
538
  # If set to false, column names will be autogenerated in the
485
539
  # following format: `column_x`, with `x` being an
486
540
  # enumeration over every column in the dataset starting at 1.
487
- # @param sep [String]
488
- # Single byte character to use as delimiter in the file.
489
- # @param comment_char [String]
490
- # Single byte character that indicates the start of a comment line,
491
- # for instance `#`.
541
+ # @param separator [String]
542
+ # Single byte character to use as separator in the file.
543
+ # @param comment_prefix [String]
544
+ # A string used to indicate the start of a comment line. Comment lines are skipped
545
+ # during parsing. Common examples of comment prefixes are `#` and `//`.
492
546
  # @param quote_char [String]
493
547
  # Single byte character used for csv quoting.
494
- # Set to None to turn off special handling and escaping of quotes.
548
+ # Set to nil to turn off special handling and escaping of quotes.
495
549
  # @param skip_rows [Integer]
496
550
  # Start reading after `skip_rows` lines. The header will be parsed at this
497
551
  # offset.
498
- # @param dtypes [Object]
499
- # Overwrite dtypes during inference.
552
+ # @param skip_lines [Integer]
553
+ # Start reading after `skip_lines` lines. The header will be parsed at this
554
+ # offset. Note that CSV escaping will not be respected when skipping lines.
555
+ # If you want to skip valid CSV rows, use `skip_rows`.
556
+ # @param schema [Object]
557
+ # Provide the schema. This means that polars doesn't do schema inference.
558
+ # This argument expects the complete schema, whereas `schema_overrides` can be
559
+ # used to partially overwrite a schema. Note that the order of the columns in
560
+ # the provided `schema` must match the order of the columns in the CSV being read.
561
+ # @param schema_overrides [Object]
562
+ # Overwrite dtypes for specific or all columns during schema inference.
500
563
  # @param null_values [Object]
501
564
  # Values to interpret as null values. You can provide a:
502
565
  #
503
566
  # - `String`: All values equal to this string will be null.
504
567
  # - `Array`: All values equal to any string in this array will be null.
505
568
  # - `Hash`: A hash that maps column name to a null value string.
569
+ # @param missing_utf8_is_empty_string [Boolean]
570
+ # By default a missing value is considered to be null; if you would prefer missing
571
+ # utf8 values to be treated as the empty string you can set this param true.
506
572
  # @param ignore_errors [Boolean]
507
573
  # Try to keep reading lines if some lines yield errors.
508
574
  # First try `infer_schema_length: 0` to read all columns as
@@ -513,6 +579,11 @@ module Polars
513
579
  # Apply a function over the column names.
514
580
  # This can be used to update a schema just in time, thus before
515
581
  # scanning.
582
+ # @param infer_schema [Boolean]
583
+ # When `true`, the schema is inferred from the data using the first
584
+ # `infer_schema_length` rows.
585
+ # When `false`, the schema is not inferred and will be `Polars::String` if not
586
+ # specified in `schema` or `schema_overrides`.
516
587
  # @param infer_schema_length [Integer]
517
588
  # Maximum number of lines to read to infer schema.
518
589
  # If set to 0, all columns will be read as `:str`.
@@ -528,64 +599,167 @@ module Polars
528
599
  # Reallocate to contiguous memory when all chunks/ files are parsed.
529
600
  # @param skip_rows_after_header [Integer]
530
601
  # Skip this number of rows when the header is parsed.
531
- # @param row_count_name [String]
602
+ # @param row_index_name [String]
532
603
  # If not nil, this will insert a row count column with the given name into
533
604
  # the DataFrame.
534
- # @param row_count_offset [Integer]
605
+ # @param row_index_offset [Integer]
535
606
  # Offset to start the row_count column (only used if the name is set).
536
- # @param parse_dates [Boolean]
607
+ # @param try_parse_dates [Boolean]
537
608
  # Try to automatically parse dates. If this does not succeed,
538
609
  # the column remains of data type `:str`.
539
610
  # @param eol_char [String]
540
611
  # Single byte end of line character.
612
+ # @param new_columns [Array]
613
+ # Provide an explicit list of string column names to use (for example, when
614
+ # scanning a headerless CSV file). If the given list is shorter than the width of
615
+ # the DataFrame the remaining columns will have their original name.
616
+ # @param raise_if_empty [Boolean]
617
+ # When there is no data in the source, `NoDataError` is raised. If this parameter
618
+ # is set to false, an empty LazyFrame (with no columns) is returned instead.
541
619
  # @param truncate_ragged_lines [Boolean]
542
620
  # Truncate lines that are longer than the schema.
621
+ # @param decimal_comma [Boolean]
622
+ # Parse floats using a comma as the decimal separator instead of a period.
623
+ # @param glob [Boolean]
624
+ # Expand path given via globbing rules.
625
+ # @param storage_options [Hash]
626
+ # Options that indicate how to connect to a cloud provider.
627
+ #
628
+ # The cloud providers currently supported are AWS, GCP, and Azure.
629
+ # See supported keys here:
630
+ #
631
+ # * [aws](https://docs.rs/object_store/latest/object_store/aws/enum.AmazonS3ConfigKey.html)
632
+ # * [gcp](https://docs.rs/object_store/latest/object_store/gcp/enum.GoogleConfigKey.html)
633
+ # * [azure](https://docs.rs/object_store/latest/object_store/azure/enum.AzureConfigKey.html)
634
+ # * Hugging Face (`hf://`): Accepts an API key under the `token` parameter: \
635
+ # `{'token': '...'}`, or by setting the `HF_TOKEN` environment variable.
636
+ #
637
+ # If `storage_options` is not provided, Polars will try to infer the information
638
+ # from environment variables.
639
+ # @param credential_provider [Object]
640
+ # Provide a function that can be called to provide cloud storage
641
+ # credentials. The function is expected to return a hash of
642
+ # credential keys along with an optional credential expiry time.
643
+ # @param retries [Integer]
644
+ # Number of retries if accessing a cloud instance fails.
645
+ # @param file_cache_ttl [Integer]
646
+ # Amount of time to keep downloaded cloud files since their last access time,
647
+ # in seconds. Uses the `POLARS_FILE_CACHE_TTL` environment variable
648
+ # (which defaults to 1 hour) if not given.
649
+ # @param include_file_paths [String]
650
+ # Include the path of the source file(s) as a column with this name.
651
+ # @param missing_columns ['insert', 'raise']
652
+ # Configuration for behavior when columns defined in the schema are
653
+ # missing from the data:
654
+ #
655
+ # * `"insert"`: Insert the missing columns with NULL values.
656
+ # * `"raise"`: Raise an error.
543
657
  #
544
658
  # @return [LazyFrame]
545
659
  def scan_csv(
546
660
  source,
547
661
  has_header: true,
548
- sep: ",",
549
- comment_char: nil,
662
+ separator: ",",
663
+ comment_prefix: nil,
550
664
  quote_char: '"',
551
665
  skip_rows: 0,
552
- dtypes: nil,
666
+ skip_lines: 0,
667
+ schema: nil,
668
+ schema_overrides: nil,
553
669
  null_values: nil,
554
670
  missing_utf8_is_empty_string: false,
555
671
  ignore_errors: false,
556
- cache: true,
672
+ cache: nil,
557
673
  with_column_names: nil,
674
+ infer_schema: true,
558
675
  infer_schema_length: N_INFER_DEFAULT,
559
676
  n_rows: nil,
560
677
  encoding: "utf8",
561
678
  low_memory: false,
562
- rechunk: true,
679
+ rechunk: false,
563
680
  skip_rows_after_header: 0,
564
- row_count_name: nil,
565
- row_count_offset: 0,
566
- parse_dates: false,
681
+ row_index_name: nil,
682
+ row_index_offset: 0,
683
+ try_parse_dates: false,
567
684
  eol_char: "\n",
685
+ new_columns: nil,
568
686
  raise_if_empty: true,
569
687
  truncate_ragged_lines: false,
570
688
  decimal_comma: false,
571
- glob: true
689
+ glob: true,
690
+ storage_options: nil,
691
+ credential_provider: "auto",
692
+ retries: nil,
693
+ file_cache_ttl: nil,
694
+ include_file_paths: nil,
695
+ missing_columns: nil
572
696
  )
573
- Utils._check_arg_is_1byte("sep", sep, false)
574
- Utils._check_arg_is_1byte("comment_char", comment_char, false)
697
+ if new_columns&.any? && schema_overrides.is_a?(::Array)
698
+ msg = "expected 'schema_overrides' hash, found #{schema_overrides.inspect}"
699
+ raise TypeError, msg
700
+ elsif new_columns&.any?
701
+ if with_column_names
702
+ msg = "cannot set both `with_column_names` and `new_columns`; mutually exclusive"
703
+ raise ArgumentError, msg
704
+ end
705
+ if schema_overrides && schema_overrides.is_a?(::Array)
706
+ schema_overrides = new_columns.zip(schema_overrides).to_h
707
+ end
708
+
709
+ # wrap new column names as a callable
710
+ with_column_names = lambda do |cols|
711
+ if cols.length > new_columns.length
712
+ new_columns + cols[new_columns.length..]
713
+ else
714
+ new_columns
715
+ end
716
+ end
717
+ end
718
+
719
+ Utils._check_arg_is_1byte("separator", separator, false)
575
720
  Utils._check_arg_is_1byte("quote_char", quote_char, true)
576
721
 
577
722
  if Utils.pathlike?(source)
578
723
  source = Utils.normalize_filepath(source)
579
724
  end
580
725
 
726
+ if !infer_schema
727
+ infer_schema_length = 0
728
+ end
729
+
730
+ if !retries.nil?
731
+ msg = "the `retries` parameter was deprecated in 0.25.0; specify 'max_retries' in `storage_options` instead."
732
+ Utils.issue_deprecation_warning(msg)
733
+ storage_options = storage_options || {}
734
+ storage_options["max_retries"] = retries
735
+ end
736
+
737
+ if !file_cache_ttl.nil?
738
+ msg = "the `file_cache_ttl` parameter was deprecated in 0.25.0; specify 'file_cache_ttl' in `storage_options` instead."
739
+ Utils.issue_deprecation_warning(msg)
740
+ storage_options = storage_options || {}
741
+ storage_options["file_cache_ttl"] = file_cache_ttl
742
+ end
743
+
744
+ if !missing_columns.nil?
745
+ msg = "The `missing_columns` parameter of `scan_csv` is considered unstable."
746
+ Utils.issue_unstable_warning(msg)
747
+ end
748
+
749
+ credential_provider_builder = _init_credential_provider_builder(
750
+ credential_provider, source, storage_options, "scan_csv"
751
+ )
752
+
581
753
  _scan_csv_impl(
582
754
  source,
583
755
  has_header: has_header,
584
- sep: sep,
585
- comment_char: comment_char,
756
+ separator: separator,
757
+ comment_prefix: comment_prefix,
586
758
  quote_char: quote_char,
587
759
  skip_rows: skip_rows,
588
- dtypes: dtypes,
760
+ skip_lines: skip_lines,
761
+ schema_overrides: schema_overrides,
762
+ schema: schema,
589
763
  null_values: null_values,
590
764
  ignore_errors: ignore_errors,
591
765
  cache: cache,
@@ -596,11 +770,18 @@ module Polars
596
770
  rechunk: rechunk,
597
771
  skip_rows_after_header: skip_rows_after_header,
598
772
  encoding: encoding,
599
- row_count_name: row_count_name,
600
- row_count_offset: row_count_offset,
601
- parse_dates: parse_dates,
773
+ row_index_name: row_index_name,
774
+ row_index_offset: row_index_offset,
775
+ try_parse_dates: try_parse_dates,
602
776
  eol_char: eol_char,
603
- truncate_ragged_lines: truncate_ragged_lines
777
+ raise_if_empty: raise_if_empty,
778
+ truncate_ragged_lines: truncate_ragged_lines,
779
+ decimal_comma: decimal_comma,
780
+ glob: glob,
781
+ storage_options: storage_options,
782
+ credential_provider: credential_provider_builder,
783
+ include_file_paths: include_file_paths,
784
+ missing_columns: missing_columns
604
785
  )
605
786
  end
606
787
 
@@ -608,12 +789,15 @@ module Polars
608
789
  def _scan_csv_impl(
609
790
  source,
610
791
  has_header: true,
611
- sep: ",",
612
- comment_char: nil,
792
+ separator: ",",
793
+ comment_prefix: nil,
613
794
  quote_char: '"',
614
795
  skip_rows: 0,
615
- dtypes: nil,
796
+ skip_lines: 0,
797
+ schema: nil,
798
+ schema_overrides: nil,
616
799
  null_values: nil,
800
+ missing_utf8_is_empty_string: false,
617
801
  ignore_errors: false,
618
802
  cache: true,
619
803
  with_column_names: nil,
@@ -621,19 +805,26 @@ module Polars
621
805
  n_rows: nil,
622
806
  encoding: "utf8",
623
807
  low_memory: false,
624
- rechunk: true,
808
+ rechunk: false,
625
809
  skip_rows_after_header: 0,
626
- row_count_name: nil,
627
- row_count_offset: 0,
628
- parse_dates: false,
810
+ row_index_name: nil,
811
+ row_index_offset: 0,
812
+ try_parse_dates: false,
629
813
  eol_char: "\n",
630
- truncate_ragged_lines: true
814
+ raise_if_empty: true,
815
+ truncate_ragged_lines: true,
816
+ decimal_comma: false,
817
+ glob: true,
818
+ storage_options: nil,
819
+ credential_provider: nil,
820
+ include_file_paths: nil,
821
+ missing_columns: nil
631
822
  )
632
823
  dtype_list = nil
633
- if !dtypes.nil?
824
+ if !schema_overrides.nil?
634
825
  dtype_list = []
635
- dtypes.each do |k, v|
636
- dtype_list << [k, Utils.rb_type_to_dtype(v)]
826
+ schema_overrides.each do |k, v|
827
+ dtype_list << [k, Utils.parse_into_dtype(v)]
637
828
  end
638
829
  end
639
830
  processed_null_values = Utils._process_null_values(null_values)
@@ -645,30 +836,47 @@ module Polars
645
836
  sources = []
646
837
  end
647
838
 
839
+ # TODO: This is a hack. We conditionally set `missing_columns` to mimic
840
+ # existing behavior. This should be removed once the workaround is no
841
+ # longer needed.
842
+ if missing_columns.nil? && !schema.nil? && has_header
843
+ missing_columns = "insert"
844
+ end
845
+
648
846
  rblf =
649
847
  RbLazyFrame.new_from_csv(
650
848
  source,
651
- sep,
849
+ sources,
850
+ separator,
652
851
  has_header,
653
852
  ignore_errors,
654
853
  skip_rows,
854
+ skip_lines,
655
855
  n_rows,
656
856
  cache,
657
857
  dtype_list,
658
858
  low_memory,
659
- comment_char,
859
+ comment_prefix,
660
860
  quote_char,
661
861
  processed_null_values,
862
+ missing_utf8_is_empty_string,
662
863
  infer_schema_length,
663
864
  with_column_names,
664
865
  rechunk,
665
866
  skip_rows_after_header,
666
867
  encoding,
667
- Utils.parse_row_index_args(row_count_name, row_count_offset),
668
- parse_dates,
868
+ Utils.parse_row_index_args(row_index_name, row_index_offset),
869
+ try_parse_dates,
669
870
  eol_char,
871
+ raise_if_empty,
670
872
  truncate_ragged_lines,
671
- sources
873
+ decimal_comma,
874
+ glob,
875
+ schema,
876
+ storage_options,
877
+ credential_provider,
878
+ include_file_paths,
879
+ missing_columns
672
880
  )
673
881
  Utils.wrap_ldf(rblf)
674
882
  end