Skip to content

BUG(DEP?): Incorrect string length for mixed string and non-string array coercion #15327

Closed

Description

@seberg

In the case that the non-string values are provided before the string values, the current code gives the incorrect result datatype:

print(repr(np.array([100, "asdf"])))
# array(['100', 'asdf'], dtype='<U21')
print(repr(np.array(["asdf", 100])))
# array(['asdf', '100'], dtype='<U4')

This is because of t he current "retry-with-string" logic. The logic itself is sound, however, the first pass runs out_dtype = np.promote_types(np.int_, np.dtype("S4")) and then uses the result of this as the initial value for the second "retry" pass. When the string is first, this happens as well, but it does not affect the result.

The fix is to simply reset the elsize to 0, or even simpler just set out_dtype to NULL to begin with (I assume that no requested dtype is ever passed into that function currently, this needs a quick check though).


I would like to deprecate the above behaviour entirely forcing users to write dtype="S" or a future dtype=np.StringDType to get the behaviour.
This means making np.promote_types error for the above input. However, since we currently do not have any universal functions, this seems OK. It would also deprecate np.concatenate((["asdf"], [0.5])), but arguable that may be a good thing...

Activity

  1. seberg commented on May 4, 2020

    @seberg
    MemberAuthor

    Another issue about strings:

    In [10]: class arraylike: 
        ...:     def __array__(self, dtype=None): 
        ...:         return np.ones(5) 
        ...:          
        ...:                                                                                                                
    
    In [11]:                                                                                                                
    
    In [11]: np.array(arraylike(), "S")                                                                                          
    Out[11]: array([b'1.0', b'1.0', b'1.0', b'1.0', b'1.0'], dtype='|S32')
    
    In [12]: np.array([arraylike()], "S")                                                                                        
    Out[12]: array([b'<__main__.asdf object at 0x7f46f24da550>'], dtype='|S40')
  2. seberg commented on Nov 19, 2022

    @seberg
    MemberAuthor

    Closing the initial issue is long fixed by my array-coercion rewrite (of course we still need to just remove the string promotion in any case). The second comment example runs into a FutureWarning now, which is probably "correct".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions