MCPcopy Create free account
hub / github.com/apache/arrow / ConvertStruct

Function ConvertStruct

python/pyarrow/src/arrow/python/arrow_to_pandas.cc:664–737  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

662}
663
664Status ConvertStruct(PandasOptions options, const ChunkedArray& data,
665 PyObject** out_values) {
666 if (data.num_chunks() == 0) {
667 return Status::OK();
668 }
669 // ChunkedArray has at least one chunk
670 auto arr = checked_cast<const StructArray*>(data.chunk(0).get());
671 // Use it to cache the struct type and number of fields for all chunks
672 int32_t num_fields = arr->num_fields();
673 auto array_type = arr->type();
674 std::vector<OwnedRef> fields_data(num_fields * data.num_chunks());
675 OwnedRef dict_item;
676
677 // See notes in MakeInnerOptions.
678 options = MakeInnerOptions(std::move(options));
679 // Don't blindly convert because timestamps in lists are handled differently.
680 options.timestamp_as_object = true;
681
682 for (int c = 0; c < data.num_chunks(); c++) {
683 auto fields_data_offset = c * num_fields;
684 auto arr = checked_cast<const StructArray*>(data.chunk(c).get());
685 // Convert the struct arrays first
686 for (int32_t i = 0; i < num_fields; i++) {
687 auto field = arr->field(static_cast<int>(i));
688 // In case the field is an extension array, use .storage() to convert to Pandas
689 if (field->type()->id() == Type::EXTENSION) {
690 const ExtensionArray& arr_ext = checked_cast<const ExtensionArray&>(*field);
691 field = arr_ext.storage();
692 }
693 RETURN_NOT_OK(ConvertArrayToPandas(options, field, nullptr,
694 fields_data[i + fields_data_offset].ref()));
695 ARROW_DCHECK(PyArray_Check(fields_data[i + fields_data_offset].obj()));
696 }
697
698 // Construct a dictionary for each row
699 const bool has_nulls = data.null_count() > 0;
700 for (int64_t i = 0; i < arr->length(); ++i) {
701 if (has_nulls && arr->IsNull(i)) {
702 Py_INCREF(Py_None);
703 *out_values = Py_None;
704 } else {
705 // Build the new dict object for the row
706 dict_item.reset(PyDict_New());
707 RETURN_IF_PYERROR();
708 for (int32_t field_idx = 0; field_idx < num_fields; ++field_idx) {
709 OwnedRef field_value;
710 auto name = array_type->field(static_cast<int>(field_idx))->name();
711 if (!arr->field(static_cast<int>(field_idx))->IsNull(i)) {
712 // Value exists in child array, obtain it
713 auto array = reinterpret_cast<PyArrayObject*>(
714 fields_data[field_idx + fields_data_offset].obj());
715 auto ptr = reinterpret_cast<const char*>(PyArray_GETPTR1(array, i));
716 field_value.reset(PyArray_GETITEM(array, ptr));
717 RETURN_IF_PYERROR();
718 } else {
719 // Translate the Null to a None
720 Py_INCREF(Py_None);
721 field_value.reset(Py_None);

Callers 1

VisitMethod · 0.85

Calls 14

MakeInnerOptionsFunction · 0.85
ConvertArrayToPandasFunction · 0.85
OKFunction · 0.50
num_chunksMethod · 0.45
getMethod · 0.45
num_fieldsMethod · 0.45
typeMethod · 0.45
fieldMethod · 0.45
idMethod · 0.45
null_countMethod · 0.45
lengthMethod · 0.45
IsNullMethod · 0.45

Tested by

no test coverage detected