-
-
Notifications
You must be signed in to change notification settings - Fork 18.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
astype(str) / astype_unicode: np.nan converted to "nan" (checknull, skipna) #25353
Comments
cc @jreback : Besides the Excel issue listed in the description, this seems to ring a bell... |
I run the code recently. Passing
|
This treatment of None/np.nan is quite unexpected. I have found that this issue propagates into output of dataframes to csv / excel / clipboard, and boolean evaluation. The logical function for As an example:
srs = pd.Series([np.nan,np.nan,5])
srs
srs.any()
pd.isna(srs)
srs.to_clipboard()
0 NaN
1 NaN
2 5.0
dtype: float64
True
0 True
1 True
2 False
dtype: bool
srs = srs.astype(str,skipna=True)
srs
srs.any()
pd.isna(srs)
srs.to_clipboard()
0 nan
1 nan
2 5.0
dtype: object
'nan'
0 False
1 False
2 False
dtype: bool
|
pandas matches the behaviour of numpy
|
So, is this considered a bug or not? I now have to workaround it in my current code. Annoying because when concatenating many columns together into a string, a la
the nan's are converted to "" in the latter two columns with the |
yes this is an open bug |
Is a similar thing happening with an apply that changes the dtype from numeric to object? >>> def pretty_num(num):
... return np.nan if num is np.nan else '%0.04f' % (num,)
...
>>> nums = pd.Series([1.0, 0.1, np.nan])
>>> nums.apply(pretty_num).tolist()
['1.0000', '0.1000', 'nan']
>>> type(nums.apply(pretty_num)[2])
<class 'str'> |
Update on this? |
@abekfennessy pandas is purely volunteer - you are welcome to propose solutions and push PRs there are 3500 issues and very few volunteers |
Point taken. If I understand your comment here #35060 correctly, astype_nansafe is deprecated and the underlying cause being the issue as it originates in numpy should be resolved? |
should be closed by #37034 |
I don't think #37034 closes this ticket because the change defines the expected behaviour to be: None -> "None"
np.nan -> "nan"
NA -> "<NA>" where all three values get transformed into string types with various values, not NA types, which is what the ticket is about. |
It seems if you do: pd.Series(["foo",np.nan]).astype("string") instead of pd.Series(["foo",np.nan]).astype(str) pandas uses a String datatype with nulls and this fixed the issue for me. Specifically: s = pd.Series(["foo",np.nan]).astype("string")
type(s[1])
>> <class 'pandas._libs.missing.NAType'>
s = pd.Series(["foo",np.nan]).astype("str")
type(s[1])
>> <class 'str'> Running versions: |
ˆ ˆ ˆ |
Is this something we might want to do as breaking change in 2.0? (finally change It seems that generally people were in favor of that behaviour change, but it didn't make it in pandas 1.0 (#28176 (comment)). At that time, there was some discussion whether it should first be deprecated or not (eg in the linked PR). And of course for 2.0 that is again too late, so on the short term it is only possible as a breaking change. |
Solution tested, actually works |
With the new string dtype for pandas 3.0 (PDEP-14, #54792), we have a good opportunity to fix this issue. In #59685, I am making it so that |
Code Sample
Output
0 foo
1 nan # nan string
dtype: object
Expected output
0 foo
1 NaN # np.nan
dtype: object
Problem description
Upon converting this Series I would expect np.nan to remain np.nan but instead it is casted to string "nan". Maybe I'm alone in this and you'd actually expect that (I can't see a realistic use case for these string "nan" but well...).
So I could figure out than upon using the code sample the Series' values are processed through astype_unicode in pandas._libs.lib.
There is a skipna argument in astype_unicode and I thought it would get passed along when using pd.Series.astype(str,skipna = True) but it does not. The docstring of pd.Series.astype does not mention skipna explicitely but mentions kwargs so I tried doing this while printing skipna in astype_unicode:
Skipna stayed to the default value False in astype_unicode so it does not get passed along.
However when using astype_unicode directly setting skipna to True will not change the output of the the code sample anyways because checknull does not seem to work properly.
You can test that by printing the result of checknull in lib.pyx as I did here:
https://github.com/ThibTrip/pandas/commit/4a5c8397304e3026456d864fd5aeb7b8b9adca5f
Input
Output
Expected output
I tried patching it (so not a proper fix) using the code below but it din't work.
Also would be nice to be able to do pd.Series.astype(str,skipna = True). Whether skipna should then be True or False as default is another matter.
All of this was done in a developper version I installed today (see details below). The only alteration is the code in my commit linked above.
Sorry if this has been referenced before I searched in various ways and could not find anything except a similar issue with pd.read_excel and dtype str:
nikoskaragiannakis@694849d
Also very sorry for the mess with the commits I got a bit confused during my investigation (also I did not get enough sleep). Is it possible to delete all but my last commit? The other ones are irrelevant.
Cheers Thibault
INSTALLED VERSIONS
commit: 4a5c839
python: 3.7.2.final.0
python-bits: 64
OS: Windows
OS-release: 10
machine: AMD64
processor: Intel64 Family 6 Model 69 Stepping 1, GenuineIntel
byteorder: little
LC_ALL: None
LANG: None
LOCALE: None.None
pandas: 0.25.0.dev0+132.g4a5c83973.dirty
pytest: 4.2.0
pip: 19.0.1
setuptools: 40.7.3
Cython: 0.29.5
numpy: 1.15.4
scipy: 1.2.0
pyarrow: 0.11.1
xarray: 0.11.0
IPython: 7.2.0
sphinx: 1.8.4
patsy: 0.5.1
dateutil: 2.7.5
pytz: 2018.9
blosc: None
bottleneck: 1.2.1
tables: 3.4.4
numexpr: 2.6.9
feather: None
matplotlib: 3.0.2
openpyxl: 2.6.0
xlrd: 1.2.0
xlwt: 1.3.0
xlsxwriter: 1.1.2
lxml.etree: 4.3.1
bs4: 4.7.1
html5lib: 1.0.1
sqlalchemy: 1.2.17
pymysql: None
psycopg2: None
jinja2: 2.10
s3fs: 0.2.0
fastparquet: 0.2.1
pandas_gbq: None
pandas_datareader: None
gcsfs: None
The text was updated successfully, but these errors were encountered: