@@ -1236,15 +1236,21 @@ def from_dict(cls, data, orient="columns", dtype=None, columns=None) -> "DataFra
1236
1236
----------
1237
1237
data : dict
1238
1238
Of the form {field : array-like} or {field : dict}.
1239
- orient : {'columns', 'index'}, default 'columns'
1239
+ orient : {'columns', 'index', 'tight' }, default 'columns'
1240
1240
The "orientation" of the data. If the keys of the passed dict
1241
1241
should be the columns of the resulting DataFrame, pass 'columns'
1242
1242
(default). Otherwise if the keys should be rows, pass 'index'.
1243
+ If 'tight', assume a dict with keys ['index', 'columns', 'data',
1244
+ 'index_names', 'column_names']
1245
+
1246
+ .. versionadded:: 1.1.0
1247
+ 'tight' as an allowed value for the ``orient`` argument
1248
+
1243
1249
dtype : dtype, default None
1244
1250
Data type to force, otherwise infer.
1245
1251
columns : list, default None
1246
1252
Column labels to use when ``orient='index'``. Raises a ValueError
1247
- if used with ``orient='columns'``.
1253
+ if used with ``orient='columns'`` or ``orient='tight'`` .
1248
1254
1249
1255
.. versionadded:: 0.23.0
1250
1256
@@ -1257,6 +1263,7 @@ def from_dict(cls, data, orient="columns", dtype=None, columns=None) -> "DataFra
1257
1263
DataFrame.from_records : DataFrame from structured ndarray, sequence
1258
1264
of tuples or dicts, or DataFrame.
1259
1265
DataFrame : DataFrame object creation using constructor.
1266
+ DataFrame.to_dict : Convert the DataFrame to a dictionary.
1260
1267
1261
1268
Examples
1262
1269
--------
@@ -1279,6 +1286,20 @@ def from_dict(cls, data, orient="columns", dtype=None, columns=None) -> "DataFra
1279
1286
row_1 3 2 1 0
1280
1287
row_2 a b c d
1281
1288
1289
+ Specify ``orient='tight'`` to create the DataFrame using a 'tight'
1290
+ format.
1291
+ >>> data = {'index': [('a', 'b'), ('a', 'c')],
1292
+ 'columns': [('x', 1), ('y', 2)],
1293
+ 'data': [[1, 3], [2, 4]],
1294
+ 'index_names': ['n1', 'n2'],
1295
+ 'column_names': ['z1', 'z2']}
1296
+ >>> pd.DataFrame.from_dict(data, orient='tight')
1297
+ z1 x y
1298
+ z2 1 2
1299
+ n1 n2
1300
+ a b 1 3
1301
+ c 2 4
1302
+
1282
1303
When using the 'index' orientation, the column names can be
1283
1304
specified manually:
1284
1305
@@ -1297,13 +1318,27 @@ def from_dict(cls, data, orient="columns", dtype=None, columns=None) -> "DataFra
1297
1318
data = _from_nested_dict (data )
1298
1319
else :
1299
1320
data , index = list (data .values ()), list (data .keys ())
1300
- elif orient == "columns" :
1321
+ elif orient == "columns" or orient == "tight" :
1301
1322
if columns is not None :
1302
- raise ValueError ("cannot use columns parameter with orient='columns '" )
1323
+ raise ValueError (f "cannot use columns parameter with orient='{ orient } '" )
1303
1324
else : # pragma: no cover
1304
1325
raise ValueError ("only recognize index or columns for orient" )
1305
1326
1306
- return cls (data , index = index , columns = columns , dtype = dtype )
1327
+ if orient != "tight" :
1328
+ return cls (data , index = index , columns = columns , dtype = dtype )
1329
+ else :
1330
+ realdata = data ["data" ]
1331
+
1332
+ def create_index (indexlist , namelist ):
1333
+ if len (namelist ) > 1 :
1334
+ index = MultiIndex .from_tuples (indexlist , names = namelist )
1335
+ else :
1336
+ index = Index (indexlist , name = namelist [0 ])
1337
+ return index
1338
+
1339
+ index = create_index (data ["index" ], data ["index_names" ])
1340
+ columns = create_index (data ["columns" ], data ["column_names" ])
1341
+ return cls (realdata , index = index , columns = columns , dtype = dtype )
1307
1342
1308
1343
def to_numpy (
1309
1344
self , dtype = None , copy : bool = False , na_value = lib .no_default
@@ -1388,13 +1423,19 @@ def to_dict(self, orient="dict", into=dict):
1388
1423
- 'series' : dict like {column -> Series(values)}
1389
1424
- 'split' : dict like
1390
1425
{'index' -> [index], 'columns' -> [columns], 'data' -> [values]}
1426
+ - 'tight' : dict like
1427
+ {'index' -> [index], 'columns' -> [columns], 'data' -> [values],
1428
+ 'index_names' -> [index.names], 'column_names' -> [column.names]}
1391
1429
- 'records' : list like
1392
1430
[{column -> value}, ... , {column -> value}]
1393
1431
- 'index' : dict like {index -> {column -> value}}
1394
1432
1395
1433
Abbreviations are allowed. `s` indicates `series` and `sp`
1396
1434
indicates `split`.
1397
1435
1436
+ .. versionadded:: 1.1.0
1437
+ 'tight' as an allowed value for the ``orient`` argument
1438
+
1398
1439
into : class, default dict
1399
1440
The collections.abc.Mapping subclass used for all Mappings
1400
1441
in the return value. Can be the actual class or an empty
@@ -1444,6 +1485,10 @@ def to_dict(self, orient="dict", into=dict):
1444
1485
>>> df.to_dict('index')
1445
1486
{'row1': {'col1': 1, 'col2': 0.5}, 'row2': {'col1': 2, 'col2': 0.75}}
1446
1487
1488
+ >>> df.to_dict('tight')
1489
+ {'index': ['row1', 'row2'], 'columns': ['col1', 'col2'],
1490
+ 'data': [[1, 0.5], [2, 0.75]], 'index_names': [None], 'column_names': [None]}
1491
+
1447
1492
You can also specify the mapping type.
1448
1493
1449
1494
>>> from collections import OrderedDict, defaultdict
@@ -1519,6 +1564,23 @@ def to_dict(self, orient="dict", into=dict):
1519
1564
)
1520
1565
)
1521
1566
1567
+ elif orient == "tight" :
1568
+ return into_c (
1569
+ (
1570
+ ("index" , self .index .tolist ()),
1571
+ ("columns" , self .columns .tolist ()),
1572
+ (
1573
+ "data" ,
1574
+ [
1575
+ list (map (com .maybe_box_datetimelike , t ))
1576
+ for t in self .itertuples (index = False , name = None )
1577
+ ],
1578
+ ),
1579
+ ("index_names" , list (self .index .names )),
1580
+ ("column_names" , list (self .columns .names )),
1581
+ )
1582
+ )
1583
+
1522
1584
elif orient == "series" :
1523
1585
return into_c ((k , com .maybe_box_datetimelike (v )) for k , v in self .items ())
1524
1586
0 commit comments