@@ -13,6 +13,7 @@ use arrow_array::{
1313 GenericListArray , OffsetSizeTrait , PrimitiveArray , RecordBatch , StructArray , UInt32Array ,
1414 UInt8Array ,
1515} ;
16+ use arrow_array:: { Float32Array , Float64Array , Int16Array , Int32Array , Int64Array , Int8Array } ;
1617use arrow_buffer:: MutableBuffer ;
1718use arrow_data:: ArrayDataBuilder ;
1819use arrow_schema:: { ArrowError , DataType , Field , FieldRef , Fields , IntervalUnit , Schema } ;
@@ -235,6 +236,10 @@ pub trait FixedSizeListArrayExt {
235236 /// assert_eq!(sampled.values().len(), 160);
236237 /// ```
237238 fn sample ( & self , n : usize ) -> Result < FixedSizeListArray > ;
239+
240+ /// Ensure the [FixedSizeListArray] of Float16, Float32, Float64,
241+ /// Int8, Int16, Int32, Int64, UInt8, UInt32 type to its closest floating point type.
242+ fn convert_to_floating_point ( & self ) -> Result < FixedSizeListArray > ;
238243}
239244
240245impl FixedSizeListArrayExt for FixedSizeListArray {
@@ -253,6 +258,136 @@ impl FixedSizeListArrayExt for FixedSizeListArray {
253258 let chosen = ( 0 ..self . len ( ) as u32 ) . choose_multiple ( & mut rng, n) ;
254259 take ( self , & UInt32Array :: from ( chosen) , None ) . map ( |arr| arr. as_fixed_size_list ( ) . clone ( ) )
255260 }
261+
262+ fn convert_to_floating_point ( & self ) -> Result < FixedSizeListArray > {
263+ match self . data_type ( ) {
264+ DataType :: FixedSizeList ( field, size) => match field. data_type ( ) {
265+ DataType :: Float16 | DataType :: Float32 | DataType :: Float64 => Ok ( self . clone ( ) ) ,
266+ DataType :: Int8 => Ok ( Self :: new (
267+ Arc :: new ( arrow_schema:: Field :: new (
268+ field. name ( ) ,
269+ DataType :: Float32 ,
270+ field. is_nullable ( ) ,
271+ ) ) ,
272+ * size,
273+ Arc :: new ( Float32Array :: from_iter_values (
274+ self . values ( )
275+ . as_any ( )
276+ . downcast_ref :: < Int8Array > ( )
277+ . ok_or ( ArrowError :: ParseError (
278+ "Fail to cast primitive array to Int8Type" . to_string ( ) ,
279+ ) ) ?
280+ . into_iter ( )
281+ . filter_map ( |x| x. map ( |y| y as f32 ) ) ,
282+ ) ) ,
283+ self . nulls ( ) . cloned ( ) ,
284+ ) ) ,
285+ DataType :: Int16 => Ok ( Self :: new (
286+ Arc :: new ( arrow_schema:: Field :: new (
287+ field. name ( ) ,
288+ DataType :: Float32 ,
289+ field. is_nullable ( ) ,
290+ ) ) ,
291+ * size,
292+ Arc :: new ( Float32Array :: from_iter_values (
293+ self . values ( )
294+ . as_any ( )
295+ . downcast_ref :: < Int16Array > ( )
296+ . ok_or ( ArrowError :: ParseError (
297+ "Fail to cast primitive array to Int8Type" . to_string ( ) ,
298+ ) ) ?
299+ . into_iter ( )
300+ . filter_map ( |x| x. map ( |y| y as f32 ) ) ,
301+ ) ) ,
302+ self . nulls ( ) . cloned ( ) ,
303+ ) ) ,
304+ DataType :: Int32 => Ok ( Self :: new (
305+ Arc :: new ( arrow_schema:: Field :: new (
306+ field. name ( ) ,
307+ DataType :: Float32 ,
308+ field. is_nullable ( ) ,
309+ ) ) ,
310+ * size,
311+ Arc :: new ( Float32Array :: from_iter_values (
312+ self . values ( )
313+ . as_any ( )
314+ . downcast_ref :: < Int32Array > ( )
315+ . ok_or ( ArrowError :: ParseError (
316+ "Fail to cast primitive array to Int8Type" . to_string ( ) ,
317+ ) ) ?
318+ . into_iter ( )
319+ . filter_map ( |x| x. map ( |y| y as f32 ) ) ,
320+ ) ) ,
321+ self . nulls ( ) . cloned ( ) ,
322+ ) ) ,
323+ DataType :: Int64 => Ok ( Self :: new (
324+ Arc :: new ( arrow_schema:: Field :: new (
325+ field. name ( ) ,
326+ DataType :: Float64 ,
327+ field. is_nullable ( ) ,
328+ ) ) ,
329+ * size,
330+ Arc :: new ( Float64Array :: from_iter_values (
331+ self . values ( )
332+ . as_any ( )
333+ . downcast_ref :: < Int64Array > ( )
334+ . ok_or ( ArrowError :: ParseError (
335+ "Fail to cast primitive array to Int8Type" . to_string ( ) ,
336+ ) ) ?
337+ . into_iter ( )
338+ . filter_map ( |x| x. map ( |y| y as f64 ) ) ,
339+ ) ) ,
340+ self . nulls ( ) . cloned ( ) ,
341+ ) ) ,
342+ DataType :: UInt8 => Ok ( Self :: new (
343+ Arc :: new ( arrow_schema:: Field :: new (
344+ field. name ( ) ,
345+ DataType :: Float64 ,
346+ field. is_nullable ( ) ,
347+ ) ) ,
348+ * size,
349+ Arc :: new ( Float64Array :: from_iter_values (
350+ self . values ( )
351+ . as_any ( )
352+ . downcast_ref :: < UInt8Array > ( )
353+ . ok_or ( ArrowError :: ParseError (
354+ "Fail to cast primitive array to Int8Type" . to_string ( ) ,
355+ ) ) ?
356+ . into_iter ( )
357+ . filter_map ( |x| x. map ( |y| y as f64 ) ) ,
358+ ) ) ,
359+ self . nulls ( ) . cloned ( ) ,
360+ ) ) ,
361+ DataType :: UInt32 => Ok ( Self :: new (
362+ Arc :: new ( arrow_schema:: Field :: new (
363+ field. name ( ) ,
364+ DataType :: Float64 ,
365+ field. is_nullable ( ) ,
366+ ) ) ,
367+ * size,
368+ Arc :: new ( Float64Array :: from_iter_values (
369+ self . values ( )
370+ . as_any ( )
371+ . downcast_ref :: < UInt32Array > ( )
372+ . ok_or ( ArrowError :: ParseError (
373+ "Fail to cast primitive array to Int8Type" . to_string ( ) ,
374+ ) ) ?
375+ . into_iter ( )
376+ . filter_map ( |x| x. map ( |y| y as f64 ) ) ,
377+ ) ) ,
378+ self . nulls ( ) . cloned ( ) ,
379+ ) ) ,
380+ data_type => Err ( ArrowError :: ParseError ( format ! (
381+ "Expect either floating type or integer got {:?}" ,
382+ data_type
383+ ) ) ) ,
384+ } ,
385+ data_type => Err ( ArrowError :: ParseError ( format ! (
386+ "Expect either FixedSizeList got {:?}" ,
387+ data_type
388+ ) ) ) ,
389+ }
390+ }
256391}
257392
258393/// Force downcast of an [`Array`], such as an [`ArrayRef`], to
@@ -412,6 +547,14 @@ pub trait RecordBatchExt {
412547 /// Replace a column (specified by name) and return the new [`RecordBatch`].
413548 fn replace_column_by_name ( & self , name : & str , column : Arc < dyn Array > ) -> Result < RecordBatch > ;
414549
550+ /// Replace a column schema (specified by name) and return the new [`RecordBatch`].
551+ fn replace_column_schema_by_name (
552+ & self ,
553+ name : & str ,
554+ new_data_type : DataType ,
555+ column : Arc < dyn Array > ,
556+ ) -> Result < RecordBatch > ;
557+
415558 /// Get (potentially nested) column by qualified name.
416559 fn column_by_qualified_name ( & self , name : & str ) -> Option < & ArrayRef > ;
417560
@@ -519,6 +662,37 @@ impl RecordBatchExt for RecordBatch {
519662 Self :: try_new ( self . schema ( ) , columns)
520663 }
521664
665+ fn replace_column_schema_by_name (
666+ & self ,
667+ name : & str ,
668+ new_data_type : DataType ,
669+ column : Arc < dyn Array > ,
670+ ) -> Result < RecordBatch > {
671+ let fields = self
672+ . schema ( )
673+ . fields ( )
674+ . iter ( )
675+ . map ( |x| {
676+ if x. name ( ) != name {
677+ x. clone ( )
678+ } else {
679+ let new_field = Field :: new ( name, new_data_type. clone ( ) , x. is_nullable ( ) ) ;
680+ Arc :: new ( new_field)
681+ }
682+ } )
683+ . collect :: < Vec < _ > > ( ) ;
684+ let schema = Schema :: new_with_metadata ( fields, self . schema ( ) . metadata . clone ( ) ) ;
685+ let mut columns = self . columns ( ) . to_vec ( ) ;
686+ let field_i = self
687+ . schema ( )
688+ . fields ( )
689+ . iter ( )
690+ . position ( |f| f. name ( ) == name)
691+ . ok_or_else ( || ArrowError :: SchemaError ( format ! ( "Field {} does not exist" , name) ) ) ?;
692+ columns[ field_i] = column;
693+ Self :: try_new ( Arc :: new ( schema) , columns)
694+ }
695+
522696 fn column_by_qualified_name ( & self , name : & str ) -> Option < & ArrayRef > {
523697 let split = name. split ( '.' ) . collect :: < Vec < _ > > ( ) ;
524698 if split. is_empty ( ) {
0 commit comments