Transform a supported data type to a list of lists, and a list of headers. Supported tabular data types: * list-of-lists or another iterable of iterables * list of named tuples (usually used with headers="keys") * 2D NumPy arrays * NumPy record arrays (usually used with head
(tabular_data, headers)
| 465 | |
| 466 | |
| 467 | def _normalize_tabular_data(tabular_data, headers): |
| 468 | """Transform a supported data type to a list of lists, and a list of headers. |
| 469 | |
| 470 | Supported tabular data types: |
| 471 | |
| 472 | * list-of-lists or another iterable of iterables |
| 473 | |
| 474 | * list of named tuples (usually used with headers="keys") |
| 475 | |
| 476 | * 2D NumPy arrays |
| 477 | |
| 478 | * NumPy record arrays (usually used with headers="keys") |
| 479 | |
| 480 | * dict of iterables (usually used with headers="keys") |
| 481 | |
| 482 | * pandas.DataFrame (usually used with headers="keys") |
| 483 | |
| 484 | The first row can be used as headers if headers="firstrow", |
| 485 | column indices can be used as headers if headers="keys". |
| 486 | |
| 487 | """ |
| 488 | |
| 489 | if hasattr(tabular_data, "keys") and hasattr(tabular_data, "values"): |
| 490 | # dict-like and pandas.DataFrame? |
| 491 | if hasattr(tabular_data.values, "__call__"): |
| 492 | # likely a conventional dict |
| 493 | keys = list(tabular_data.keys()) |
| 494 | rows = list(zip_longest(*list(tabular_data.values()))) # columns have to be transposed |
| 495 | elif hasattr(tabular_data, "index"): |
| 496 | # values is a property, has .index => it's likely a pandas.DataFrame (pandas 0.11.0) |
| 497 | keys = list(tabular_data.keys()) |
| 498 | vals = tabular_data.values # values matrix doesn't need to be transposed |
| 499 | names = tabular_data.index |
| 500 | rows = [[v]+list(row) for v,row in zip(names, vals)] |
| 501 | else: |
| 502 | raise ValueError("tabular data doesn't appear to be a dict or a DataFrame") |
| 503 | |
| 504 | if headers == "keys": |
| 505 | headers = list(map(_text_type,keys)) # headers should be strings |
| 506 | |
| 507 | else: # it's a usual an iterable of iterables, or a NumPy array |
| 508 | rows = list(tabular_data) |
| 509 | |
| 510 | if (headers == "keys" and |
| 511 | hasattr(tabular_data, "dtype") and |
| 512 | getattr(tabular_data.dtype, "names")): |
| 513 | # numpy record array |
| 514 | headers = tabular_data.dtype.names |
| 515 | elif (headers == "keys" |
| 516 | and len(rows) > 0 |
| 517 | and isinstance(rows[0], tuple) |
| 518 | and hasattr(rows[0], "_fields")): # namedtuple |
| 519 | headers = list(map(_text_type, rows[0]._fields)) |
| 520 | elif headers == "keys" and len(rows) > 0: # keys are column indices |
| 521 | headers = list(map(_text_type, list(range(len(rows[0]))))) |
| 522 | |
| 523 | # take headers from the first row if necessary |
| 524 | if headers == "firstrow" and len(rows) > 0: |