Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 22 additions & 2 deletions python/pyarrow/array.pxi
Original file line number Diff line number Diff line change
Expand Up @@ -828,8 +828,23 @@ cdef class DictionaryArray(Array):


cdef class StructArray(Array):

@staticmethod
def from_arrays(field_names, arrays):
def from_arrays(arrays, names=None):
"""
Construct StructArray from collection of arrays representing each field
in the struct

Parameters
----------
arrays : sequence of Array
names : List[str]
Field names

Returns
-------
result : StructArray
"""
cdef:
Array array
shared_ptr[CArray] c_array
Expand All @@ -839,6 +854,11 @@ cdef class StructArray(Array):
ssize_t length
ssize_t i

if names is None:
raise ValueError('Names are currently required')

arrays = [asarray(x) for x in arrays]

num_arrays = len(arrays)
if num_arrays == 0:
raise ValueError("arrays list is empty")
Expand All @@ -855,7 +875,7 @@ cdef class StructArray(Array):
cdef DataType struct_type = struct([
field(name, array.type)
for name, array in
zip(field_names, arrays)
zip(names, arrays)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If names is None this will fail. What's the desired behavior in the case that names is None?

])

c_result.reset(new CStructArray(struct_type.sp_type, length, c_arrays))
Expand Down
28 changes: 26 additions & 2 deletions python/pyarrow/tests/test_convert_builtin.py
Original file line number Diff line number Diff line change
Expand Up @@ -493,8 +493,8 @@ def test_structarray():
strs = pa.array([u'a', None, u'c'], type=pa.string())
bools = pa.array([True, False, None], type=pa.bool_())
arr = pa.StructArray.from_arrays(
['ints', 'strs', 'bools'],
[ints, strs, bools])
[ints, strs, bools],
['ints', 'strs', 'bools'])

expected = [
{'ints': None, 'strs': u'a', 'bools': True},
Expand Down Expand Up @@ -529,3 +529,27 @@ def test_struct_from_dicts():
{'a': None, 'b': None, 'c': None},
{'a': None, 'b': 'bar', 'c': None}]
assert arr.to_pylist() == expected


def test_structarray_from_arrays_coerce():
# ARROW-1706
ints = [None, 2, 3]
strs = [u'a', None, u'c']
bools = [True, False, None]
ints_nonnull = [1, 2, 3]

arrays = [ints, strs, bools, ints_nonnull]
result = pa.StructArray.from_arrays(arrays,
['ints', 'strs', 'bools',
'int_nonnull'])
expected = pa.StructArray.from_arrays(
[pa.array(ints, type='int64'),
pa.array(strs, type='utf8'),
pa.array(bools),
pa.array(ints_nonnull, type='int64')],
['ints', 'strs', 'bools', 'int_nonnull'])

with pytest.raises(ValueError):
pa.StructArray.from_arrays(arrays)

assert result.equals(expected)
4 changes: 2 additions & 2 deletions python/pyarrow/tests/test_convert_pandas.py
Original file line number Diff line number Diff line change
Expand Up @@ -1153,8 +1153,8 @@ def test_structarray(self):
strs = pa.array([u'a', None, u'c'], type=pa.string())
bools = pa.array([True, False, None], type=pa.bool_())
arr = pa.StructArray.from_arrays(
['ints', 'strs', 'bools'],
[ints, strs, bools])
[ints, strs, bools],
['ints', 'strs', 'bools'])

expected = pd.Series([
{'ints': None, 'strs': u'a', 'bools': True},
Expand Down