Skip to content

Commit c111790

Browse files
committed
TST: Tests and fix for unhandled data types in Excel writers.
Added tests and a fix for unhandled numpy data types in the Excel writers. Issue #3122.
1 parent bea5051 commit c111790

File tree

2 files changed

+63
-41
lines changed

2 files changed

+63
-41
lines changed

pandas/io/excel.py

+8-9
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from pandas.core import config
1717
from pandas.core.common import pprint_thing
1818
import pandas.compat as compat
19+
import pandas.core.common as com
1920
from warnings import warn
2021

2122
__all__ = ["read_excel", "ExcelWriter", "ExcelFile"]
@@ -290,20 +291,20 @@ def __enter__(self):
290291
def __exit__(self, exc_type, exc_value, traceback):
291292
self.close()
292293

293-
294294
def _trim_excel_header(row):
295295
# trim header row so auto-index inference works
296296
# xlrd uses '' , openpyxl None
297297
while len(row) > 0 and (row[0] == '' or row[0] is None):
298298
row = row[1:]
299299
return row
300300

301-
302301
def _conv_value(val):
303-
# convert value for excel dump
304-
if isinstance(val, np.int64):
302+
# Convert numpy types to Python types for the Excel writers.
303+
if com.is_integer(val):
305304
val = int(val)
306-
elif isinstance(val, np.bool8):
305+
elif com.is_float(val):
306+
val = float(val)
307+
elif com.is_bool(val):
307308
val = bool(val)
308309
elif isinstance(val, Period):
309310
val = "%s" % val
@@ -686,8 +687,6 @@ def write_cells(self, cells, sheet_name=None, startrow=0, startcol=0):
686687
style_dict = {}
687688

688689
for cell in cells:
689-
val = _conv_value(cell.val)
690-
691690
num_format_str = None
692691
if isinstance(cell.val, datetime.datetime):
693692
num_format_str = "YYYY-MM-DD HH:MM:SS"
@@ -709,11 +708,11 @@ def write_cells(self, cells, sheet_name=None, startrow=0, startcol=0):
709708
startrow + cell.mergestart,
710709
startcol + cell.col,
711710
startcol + cell.mergeend,
712-
val, style)
711+
cell.val, style)
713712
else:
714713
wks.write(startrow + cell.row,
715714
startcol + cell.col,
716-
val, style)
715+
cell.val, style)
717716

718717
def _convert_to_style(self, style_dict, num_format_str=None):
719718
"""

pandas/io/tests/test_excel.py

+55-32
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,6 @@ def test_excel_table_sheet_by_index(self):
221221
(self.xlsx1, self.csv1)]:
222222
self.check_excel_table_sheet_by_index(filename, csvfile)
223223

224-
225224
def test_excel_table(self):
226225
_skip_if_no_xlrd()
227226

@@ -405,7 +404,6 @@ def test_mixed(self):
405404
recons = reader.parse('test1', index_col=0)
406405
tm.assert_frame_equal(self.mixed_frame, recons)
407406

408-
409407
def test_tsframe(self):
410408
_skip_if_no_xlrd()
411409
ext = self.ext
@@ -419,45 +417,70 @@ def test_tsframe(self):
419417
recons = reader.parse('test1')
420418
tm.assert_frame_equal(df, recons)
421419

422-
def test_int64(self):
420+
def test_int_types(self):
423421
_skip_if_no_xlrd()
424422
ext = self.ext
425-
path = '__tmp_to_excel_from_excel_int64__.' + ext
426-
427-
with ensure_clean(path) as path:
428-
self.frame['A'][:5] = nan
429-
430-
self.frame.to_excel(path, 'test1')
431-
self.frame.to_excel(path, 'test1', cols=['A', 'B'])
432-
self.frame.to_excel(path, 'test1', header=False)
433-
self.frame.to_excel(path, 'test1', index=False)
423+
path = '__tmp_to_excel_from_excel_int_types__.' + ext
434424

435-
# Test np.int64, values read come back as float
436-
frame = DataFrame(np.random.randint(-10, 10, size=(10, 2)), dtype=np.int64)
437-
frame.to_excel(path, 'test1')
438-
reader = ExcelFile(path)
439-
recons = reader.parse('test1').astype(np.int64)
440-
tm.assert_frame_equal(frame, recons, check_dtype=False)
425+
for np_type in (np.int8, np.int16, np.int32, np.int64):
441426

442-
def test_bool(self):
427+
with ensure_clean(path) as path:
428+
self.frame['A'][:5] = nan
429+
430+
self.frame.to_excel(path, 'test1')
431+
self.frame.to_excel(path, 'test1', cols=['A', 'B'])
432+
self.frame.to_excel(path, 'test1', header=False)
433+
self.frame.to_excel(path, 'test1', index=False)
434+
435+
# Test np.int values read come back as float.
436+
frame = DataFrame(np.random.randint(-10, 10, size=(10, 2)),
437+
dtype=np_type)
438+
frame.to_excel(path, 'test1')
439+
reader = ExcelFile(path)
440+
recons = reader.parse('test1').astype(np_type)
441+
tm.assert_frame_equal(frame, recons, check_dtype=False)
442+
443+
def test_float_types(self):
443444
_skip_if_no_xlrd()
444445
ext = self.ext
445-
path = '__tmp_to_excel_from_excel_bool__.' + ext
446+
path = '__tmp_to_excel_from_excel_float_types__.' + ext
446447

447-
with ensure_clean(path) as path:
448-
self.frame['A'][:5] = nan
448+
for np_type in (np.float16, np.float32, np.float64):
449+
with ensure_clean(path) as path:
450+
self.frame['A'][:5] = nan
449451

450-
self.frame.to_excel(path, 'test1')
451-
self.frame.to_excel(path, 'test1', cols=['A', 'B'])
452-
self.frame.to_excel(path, 'test1', header=False)
453-
self.frame.to_excel(path, 'test1', index=False)
452+
self.frame.to_excel(path, 'test1')
453+
self.frame.to_excel(path, 'test1', cols=['A', 'B'])
454+
self.frame.to_excel(path, 'test1', header=False)
455+
self.frame.to_excel(path, 'test1', index=False)
454456

455-
# Test reading/writing np.bool8, roundtrip only works for xlsx
456-
frame = (DataFrame(np.random.randn(10, 2)) >= 0)
457-
frame.to_excel(path, 'test1')
458-
reader = ExcelFile(path)
459-
recons = reader.parse('test1').astype(np.bool8)
460-
tm.assert_frame_equal(frame, recons)
457+
# Test np.float values read come back as float.
458+
frame = DataFrame(np.random.random_sample(10), dtype=np_type)
459+
frame.to_excel(path, 'test1')
460+
reader = ExcelFile(path)
461+
recons = reader.parse('test1').astype(np_type)
462+
tm.assert_frame_equal(frame, recons, check_dtype=False)
463+
464+
def test_bool_types(self):
465+
_skip_if_no_xlrd()
466+
ext = self.ext
467+
path = '__tmp_to_excel_from_excel_bool_types__.' + ext
468+
469+
for np_type in (np.bool8, np.bool_):
470+
with ensure_clean(path) as path:
471+
self.frame['A'][:5] = nan
472+
473+
self.frame.to_excel(path, 'test1')
474+
self.frame.to_excel(path, 'test1', cols=['A', 'B'])
475+
self.frame.to_excel(path, 'test1', header=False)
476+
self.frame.to_excel(path, 'test1', index=False)
477+
478+
# Test np.bool values read come back as float.
479+
frame = (DataFrame([1, 0, True, False], dtype=np_type))
480+
frame.to_excel(path, 'test1')
481+
reader = ExcelFile(path)
482+
recons = reader.parse('test1').astype(np_type)
483+
tm.assert_frame_equal(frame, recons)
461484

462485
def test_sheets(self):
463486
_skip_if_no_xlrd()

0 commit comments

Comments
 (0)