python.observation.field_structure
Created on Sun Oct 2 22:24:59 2022
@author: philippe@loco-labs.io
The python.observation.field_structure module contains the FieldStructure class
(python.observation.field.Field methods).
1# -*- coding: utf-8 -*- 2""" 3Created on Sun Oct 2 22:24:59 2022 4 5@author: philippe@loco-labs.io 6 7The `python.observation.field_structure` module contains the `FieldStructure` class 8(`python.observation.field.Field` methods). 9""" 10from collections import defaultdict, Counter 11 12from observation.util import util 13from observation.esconstante import ES 14from observation.field_interface import FieldError 15 16class FieldStructure: 17 '''this class includes Field methods : 18 19 *add - update methods* 20 21 - `FieldStructure.append` 22 - `FieldStructure.setcodecvalue` 23 - `FieldStructure.setcodeclist` 24 - `FieldStructure.setname` 25 - `FieldStructure.setkeys` 26 - `FieldStructure.setlistvalue` 27 - `FieldStructure.setvalue` 28 29 *transform methods* 30 31 - `FieldStructure.coupling` 32 - `FieldStructure.extendkeys` 33 - `FieldStructure.full` 34 - `FieldStructure.reindex` 35 - `FieldStructure.reorder` 36 - `FieldStructure.sort` 37 - `FieldStructure.tocoupled` 38 - `FieldStructure.tostdcodec` 39 40 *getters methods* 41 42 - `FieldStructure.couplinginfos` 43 - `FieldStructure.derkeys` 44 - `FieldStructure.getduplicates` 45 - `FieldStructure.iscrossed` 46 - `FieldStructure.iscoupled` 47 - `FieldStructure.isderived` 48 - `FieldStructure.islinked` 49 - `FieldStructure.isvalue` 50 - `FieldStructure.iskeysfromderkeys` 51 - `FieldStructure.keysfromderkeys` 52 - `FieldStructure.keytoval` 53 - `FieldStructure.loc` 54 - `FieldStructure.recordfromkeys` 55 - `FieldStructure.recordfromvalue` 56 - `FieldStructure.valtokey` ''' 57 58 def append(self, value, unique=True): 59 '''add a new value 60 61 *Parameters* 62 63 - **value** : new object value 64 - **unique** : boolean (default True) - If False, duplication codec if value is present 65 66 *Returns* : key of value ''' 67 #value = Ntv.obj(value) 68 value = self.s_to_i(value) 69 if value in self._codec and unique: 70 key = self._codec.index(value) 71 else: 72 key = len(self._codec) 73 self._codec.append(value) 74 self._keys.append(key) 75 return key 76 77 def coupling(self, idx, derived=True, duplicate=True, reindex=False): 78 ''' 79 Transform indexes in coupled or derived indexes (codec extension). 80 If derived option is True, self._codec is extended and idx codec not, 81 else, both are coupled and both codec are extended. 82 83 *Parameters* 84 85 - **idx** : single Field or list of Field to be coupled or derived. 86 - **derived** : boolean (default : True) - if True result is derived, 87 if False coupled 88 - **duplicate** : boolean (default: True) - if True, return duplicate records 89 (only for self index) 90 - **reindex** : boolean (default : False). If True self.index is reindexed 91 with default codec. But if not derived, idx indexes MUST to be reindexed. 92 93 *Returns* : tuple with duplicate records (errors) if 'duplicate', None else''' 94 if not isinstance(idx, list): 95 index = [idx] 96 else: 97 index = idx 98 idxzip = self.__class__(list(zip(*([self._keys] + [ix._keys for ix in index]))), 99 reindex=True) 100 self.tocoupled(idxzip) 101 if not derived: 102 for ind in index: 103 ind.tocoupled(idxzip) 104 if duplicate: 105 return self.getduplicates(reindex) 106 if reindex: 107 self.reindex() 108 return 109 110 def couplinginfos(self, other, default=False): 111 '''return a dict with the coupling info between other (distance, ratecpl, 112 rateder, dist, disttomin, disttomax, distmin, distmax, diff, typecoupl) 113 114 *Parameters* 115 116 - **other** : other index to compare 117 - **default** : comparison with default codec 118 119 *Returns* : dict''' 120 if default: 121 return util.couplinginfos(self.values, other.values) 122 if min(len(self), len(other)) == 0: 123 return {'dist': 0, 'rateder': 0, 'disttomin': 0, 'disttomax': 0, 124 'distmin': 0, 'distmax': 0, 'diff': 0, 'typecoupl': 'null', 125 'distance': 0, 'ratecpl': 0} 126 xs = len(self._codec) # xs 127 xo = len(other._codec) # xo 128 dmin = max(xs, xo) # dmin 129 dmax = xs * xo # dmax 130 diff = abs(xs - xo) # diff 131 if min(xs, xo) == 1: 132 ratecpl = 0 133 if dmax - dmin + diff != 0: 134 ratecpl = diff / (dmax - dmin + diff) # 135 if xs == 1: 136 typec = 'derived' 137 else: 138 typec = 'derive' 139 return {'dist': dmin, 'rateder': 0, 'disttomin': 0, 'disttomax': 0, 140 'distmin': dmin, 'distmax': dmax, 'diff': diff, 141 'typecoupl': typec, 'distance': diff, 'ratecpl': ratecpl} 142 xso = len(util.tocodec([tuple((v1, v2)) # xab 143 for v1, v2 in zip(self._keys, other._keys)])) 144 dic = {'dist': xso, 'distmin': dmin, 'distmax': dmax, 'diff': diff, 145 'rateder': (xso - dmin) / (dmax - dmin), # rateDer 146 'disttomin': xso - dmin, 147 'disttomax': dmax - xso, 148 'distance': xso - dmin + diff, 149 'ratecpl': (xso - dmin + diff) / (dmax - dmin + diff)} #rateCpl 150 if dic['rateder'] == 0 and dic['diff'] == 0: 151 dic['typecoupl'] = 'coupled' 152 elif dic['rateder'] == 0 and xs < xo: 153 dic['typecoupl'] = 'derived' 154 elif dic['rateder'] == 0 and xs > xo: 155 dic['typecoupl'] = 'derive' 156 elif dic['rateder'] == 1: 157 dic['typecoupl'] = 'crossed' 158 elif xs < xo: 159 dic['typecoupl'] = 'linked' 160 else: 161 dic['typecoupl'] = 'link' 162 return dic 163 164 def derkeys(self, parent): 165 '''return keys derived from parent keys 166 167 *Parameters* 168 169 - **parent** : Field - parent 170 171 *Returns* : list of keys''' 172 derkey = [ES.nullparent] * len(parent._codec) 173 for i in range(len(self)): 174 derkey[parent._keys[i]] = self._keys[i] 175 if min(derkey) < 0: 176 raise FieldError("parent is not a derive Field") 177 return derkey 178 179 def extendkeys(self, keys): 180 '''add keys to the Field 181 182 *Parameters* 183 184 - **keys** : list of int (value lower or equal than actual keys) 185 186 *Returns* : None ''' 187 if min(keys) < 0 or max(keys) > len(self._codec) - 1: 188 raise FieldError('keys not consistent with codec') 189 self._keys += keys 190 191 @staticmethod 192 def full(listidx): 193 '''tranform a list of indexes in crossed indexes (value extension). 194 195 *Parameters* 196 197 - **listidx** : list of Field to transform 198 199 *Returns* : tuple of records added ''' 200 idx1 = listidx[0] 201 for idx in listidx: 202 if len(idx) != len(idx): 203 return None 204 leninit = len(idx1) 205 keysadd = util.idxfull(listidx) 206 for idx, keys in zip(listidx, keysadd): 207 idx._keys += keys 208 return tuple(range(leninit, len(idx1))) 209 210 def getduplicates(self, reindex=False): 211 ''' calculate items with duplicate codec 212 213 *Parameters* 214 215 - **reindex** : boolean (default : False). If True index is reindexed with default codec 216 217 *Returns* : tuple of items with duplicate codec''' 218 count = Counter(self._codec) 219 defcodec = list(count - Counter(list(count))) 220 dkeys = defaultdict(list) 221 for key, ind in zip(self._keys, range(len(self))): 222 dkeys[key].append(ind) 223 dcodec = defaultdict(list) 224 for key, ind in zip(self._codec, range(len(self._codec))): 225 dcodec[key].append(ind) 226 duplicates = [] 227 for item in defcodec: 228 for codecitem in dcodec[item]: 229 duplicates += dkeys[codecitem] 230 if reindex: 231 self.reindex() 232 return tuple(duplicates) 233 234 def iscrossed(self, other): 235 '''return True if self is crossed to other''' 236 return self.couplinginfos(other)['rateder'] == 1.0 237 238 def iscoupled(self, other): 239 '''return True if self is coupled to other''' 240 info = self.couplinginfos(other) 241 return info['diff'] == 0 and info['rateder'] == 0 242 243 def isderived(self, other): 244 '''return True if self is derived from other''' 245 info = self.couplinginfos(other) 246 return info['diff'] != 0 and info['rateder'] == 0.0 247 248 def iskeysfromderkeys(self, other): 249 '''return True if self._keys is relative from other._keys''' 250 leng = len(other._codec) 251 if leng % len(self._codec) != 0: 252 return False 253 keys = [(i*len(self._codec))//leng for i in range(leng)] 254 return self.__class__.keysfromderkeys(other._keys, keys) == self._keys 255 256 def islinked(self, other): 257 '''return True if self is linked to other''' 258 rate = self.couplinginfos(other)['rateder'] 259 return 0.0 < rate < 1.0 260 261 def isvalue(self, value, extern=True): 262 ''' return True if value is in index values 263 264 *Parameters* 265 266 - **value** : value to check 267 - **extern** : if True, compare value to external representation of self.value, 268 else, internal''' 269 if extern: 270 return value in self.val 271 return value in self.values 272 273 def keytoval(self, key, extern=True): 274 ''' return the value of a key 275 276 *Parameters* 277 278 - **key** : key to convert into values 279 - **extern** : if True, return string representation else, internal value 280 281 *Returns* 282 283 - **int** : first key finded (None else)''' 284 if key < 0 or key >= len(self._codec): 285 return None 286 if extern: 287 return self.cod[key] 288 return self._codec[key] 289 290 @staticmethod 291 def keysfromderkeys(parentkeys, derkeys): 292 '''return keys from parent keys and derkeys 293 294 *Parameters* 295 296 - **parentkeys** : list of keys from parent 297 - **derkeys** : list of derived keys 298 299 *Returns* : list of keys''' 300 #return [derkeys[parentkeys[i]] for i in range(len(parentkeys))] 301 return [derkeys[pkey] for pkey in parentkeys] 302 303 def loc(self, value, extern=True): 304 '''return a list of record number with value 305 306 *Parameters* 307 308 - **value** : value to check 309 - **extern** : if True, compare value to external representation of self.value, 310 else, internal 311 312 *Returns* 313 314 - **list of int** : list of record number finded (None else)''' 315 return self.recordfromvalue(value, extern=extern) 316 317 def recordfromvalue(self, value, extern=True): 318 '''return a list of record number with value 319 320 *Parameters* 321 322 - **value** : value to check 323 - **extern** : if True, compare value to external representation of self.value, 324 else, internal 325 326 *Returns* 327 328 - **list of int** : list of record number finded (None else)''' 329 330 if extern: 331 value = self.s_to_i(value) 332 if not value in self._codec: 333 return None 334 listkeys = [cod for cod, val in zip( 335 range(len(self._codec)), self._codec) if val == value] 336 return self.recordfromkeys(listkeys) 337 338 def recordfromkeys(self, listkeys): 339 '''return a list of record number with key in listkeys 340 341 *Parameters* 342 343 - **listkeys** : list of keys to check 344 345 *Returns* 346 347 - **list of int** : list of record number finded (None else)''' 348 349 return [rec for rec, key in zip(range(len(self)), self._keys) if key in listkeys] 350 351 def reindex(self, codec=None): 352 '''apply a reordered codec. If None, a new default codec is apply. 353 354 *Parameters* 355 356 - **codec** : list (default None) - reordered codec to apply. 357 358 *Returns* : self''' 359 360 if not codec: 361 codec = util.tocodec(self.values) 362 self._keys = util.reindex(self._keys, self._codec, codec) 363 self._codec = codec 364 return self 365 366 def reorder(self, sort=None, inplace=True): 367 '''Change the Field order with a new order define by sort and reset the codec. 368 369 *Parameters* 370 371 - **sort** : int list (default None)- new record order to apply. If None, no change. 372 - **inplace** : boolean (default True) - if True, new order is apply to self, 373 if False a new Field is created. 374 375 *Returns* 376 377 - **Field** : self if inplace, new Field if not inplace''' 378 values = util.reorder(self.values, sort) 379 codec, keys = util.resetidx(values) 380 if inplace: 381 self._keys = keys 382 self._codec = codec 383 return None 384 return self.__class__(name=self.name, codec=codec, keys=keys) 385 386 def setcodecvalue(self, oldvalue, newvalue, extern=True, 387 nameonly=False, valueonly=False): 388 '''update all the oldvalue by newvalue 389 390 *Parameters* 391 392 - **oldvalue** : list of values to replace 393 - **newvalue** : list of new value to apply 394 - **extern** : if True, the newvalue has external representation, else internal 395 - **nameonly** : if True, only the name of ESValue is changed 396 - **valueonly** : if True, only the value of ESValue is changed 397 398 *Returns* : int - last codec rank updated (-1 if None)''' 399 if extern: 400 newvalue = self.s_to_i(newvalue) 401 oldvalue = self.s_to_i(oldvalue) 402 rank = -1 403 for i in range(len(self._codec)): 404 if self._codec[i] == oldvalue: 405 if nameonly: 406 self._codec[i].setName(newvalue.ntv_name) 407 elif valueonly: 408 self._codec[i].setValue(newvalue.ntv_value) 409 else: 410 self._codec[i] = newvalue 411 rank = i 412 return rank 413 414 def setcodeclist(self, listcodec, extern=True, nameonly=False, valueonly=False): 415 '''update codec with listcodec values 416 417 *Parameters* 418 419 - **listcodec** : list of new codec values to apply 420 - **extern** : if True, the newvalue has external representation, else internal 421 - **nameonly** : if True, only the name of ESValue is changed 422 - **valueonly** : if True, only the value of ESValue is changed 423 424 *Returns* : int - last codec rank updated (-1 if None)''' 425 if extern: 426 listcodec = self.l_to_i(listcodec) 427 self._codec = listcodec 428 429 def set_keys(self, keys): 430 ''' _keys setters ''' 431 self._keys = keys 432 433 def set_codec(self, codec): 434 ''' _codec setters ''' 435 self._codec = codec 436 437 def setkeys(self, keys, inplace=True): 438 '''apply new keys (replace codec with extended codec from parent keys) 439 440 *Parameters* 441 442 - **keys** : list of keys to apply 443 - **inplace** : if True, update self data, else create a new Field 444 445 *Returns* : self or new Field''' 446 codec = util.tocodec(self.values, keys) 447 if inplace: 448 self._codec = codec 449 self._keys = keys 450 return self 451 return self.__class__(codec=codec, name=self.name, keys=keys) 452 453 def setname(self, name): 454 '''update the Field name 455 456 *Parameters* 457 458 - **name** : str to set into name 459 460 *Returns* : boolean - True if update''' 461 if isinstance(name, str): 462 self.name = name 463 return True 464 return False 465 466 def setvalue(self, ind, value, extern=True, nameonly=False, valueonly=False): 467 '''update a value at the rank ind (and update codec and keys) 468 469 *Parameters* 470 471 - **ind** : rank of the value 472 - **value** : new value 473 - **extern** : if True, the value has external representation, else internal 474 - **nameonly** : if True, only the name of ESValue is changed 475 - **valueonly** : if True, only the value of ESValue is changed 476 477 *Returns* : None''' 478 if extern: 479 value = self.s_to_i(value) 480 values = self.values 481 if nameonly: 482 values[ind].setName(values.ntv_name) 483 elif valueonly: 484 values[ind].setValue(values.ntv_value) 485 else: 486 values[ind] = value 487 self._codec, self._keys = util.resetidx(values) 488 489 def setlistvalue(self, listvalue, extern=True, nameonly=False, valueonly=False): 490 '''update the values (and update codec and keys) 491 492 *Parameters* 493 494 - **listvalue** : list - list of new values 495 - **extern** : if True, the value has external representation, else internal 496 - **nameonly** : if True, only the name of ESValue is changed 497 - **valueonly** : if True, only the value of ESValue is changed 498 499 *Returns* : None''' 500 if extern: 501 listvalue = self.l_to_i(listvalue) 502 values = self.values 503 for i, value_i in enumerate(listvalue): 504 if nameonly: 505 values[i].setName(value_i.ntv_name) 506 elif valueonly: 507 values[i].setValue(value_i.ntv_value) 508 else: 509 values[i] = value_i 510 self._codec, self._keys = util.resetidx(values) 511 512 def sort(self, reverse=False, inplace=True, func=str): 513 '''Define sorted index with ordered codec. 514 515 *Parameters* 516 517 - **reverse** : boolean (defaut False) - codec is sorted with reverse order 518 - **inplace** : boolean (default True) - if True, new order is apply to self, 519 if False a new Field is created. 520 - **func** : function (default str) - key used in the sorted function 521 522 *Return* 523 524 - **Field** : self if inplace, new Field if not inplace''' 525 if inplace: 526 self.reindex(codec=sorted(self._codec, reverse=reverse, key=func)) 527 self._keys.sort() 528 return self 529 oldcodec = self._codec 530 codec = sorted(oldcodec, reverse=reverse, key=str) 531 return self.__class__(name=self.name, codec=codec, 532 keys=sorted(util.reindex(self._keys, oldcodec, codec))) 533 534 def tocoupled(self, other, coupling=True): 535 ''' 536 Transform a derived index in a coupled index (keys extension) and add 537 new values to have the same length as other. 538 539 *Parameters* 540 541 - **other** : index to be coupled. 542 - **coupling** : boolean (default True) - reindex if False 543 544 *Returns* : None''' 545 dic = util.idxlink(other._keys, self._keys) 546 if not dic: 547 raise FieldError("Field is not coupled or derived from other") 548 self._codec = [self._codec[dic[i]] for i in range(len(dic))] 549 self._keys = other._keys 550 if not coupling: 551 self.reindex() 552 553 def tostdcodec(self, inplace=False, full=True): 554 ''' 555 Transform codec in full or in default codec. 556 557 *Parameters* 558 559 - **inplace** : boolean (default True) - if True, new order is apply to self, 560 - **full** : boolean (default True) - if True reindex with full codec 561 562 *Return* 563 564 - **Field** : self if inplace, new Field if not inplace''' 565 if full: 566 codec = self.values 567 keys = list(range(len(codec))) 568 else: 569 codec = util.tocodec(self.values) 570 keys = util.reindex(self._keys, self._codec, codec) 571 if inplace: 572 self._codec = codec 573 self._keys = keys 574 return self 575 return self.__class__(codec=codec, name=self.name, keys=keys) 576 577 def valtokey(self, value, extern=True): 578 '''convert a value to a key 579 580 *Parameters* 581 582 - **value** : value to convert 583 - **extern** : if True, the value has external representation, else internal 584 585 *Returns* 586 587 - **int** : first key finded (None else)''' 588 if extern: 589 value = self.s_to_i(value) 590 if value in self._codec: 591 return self._codec.index(value) 592 return None
17class FieldStructure: 18 '''this class includes Field methods : 19 20 *add - update methods* 21 22 - `FieldStructure.append` 23 - `FieldStructure.setcodecvalue` 24 - `FieldStructure.setcodeclist` 25 - `FieldStructure.setname` 26 - `FieldStructure.setkeys` 27 - `FieldStructure.setlistvalue` 28 - `FieldStructure.setvalue` 29 30 *transform methods* 31 32 - `FieldStructure.coupling` 33 - `FieldStructure.extendkeys` 34 - `FieldStructure.full` 35 - `FieldStructure.reindex` 36 - `FieldStructure.reorder` 37 - `FieldStructure.sort` 38 - `FieldStructure.tocoupled` 39 - `FieldStructure.tostdcodec` 40 41 *getters methods* 42 43 - `FieldStructure.couplinginfos` 44 - `FieldStructure.derkeys` 45 - `FieldStructure.getduplicates` 46 - `FieldStructure.iscrossed` 47 - `FieldStructure.iscoupled` 48 - `FieldStructure.isderived` 49 - `FieldStructure.islinked` 50 - `FieldStructure.isvalue` 51 - `FieldStructure.iskeysfromderkeys` 52 - `FieldStructure.keysfromderkeys` 53 - `FieldStructure.keytoval` 54 - `FieldStructure.loc` 55 - `FieldStructure.recordfromkeys` 56 - `FieldStructure.recordfromvalue` 57 - `FieldStructure.valtokey` ''' 58 59 def append(self, value, unique=True): 60 '''add a new value 61 62 *Parameters* 63 64 - **value** : new object value 65 - **unique** : boolean (default True) - If False, duplication codec if value is present 66 67 *Returns* : key of value ''' 68 #value = Ntv.obj(value) 69 value = self.s_to_i(value) 70 if value in self._codec and unique: 71 key = self._codec.index(value) 72 else: 73 key = len(self._codec) 74 self._codec.append(value) 75 self._keys.append(key) 76 return key 77 78 def coupling(self, idx, derived=True, duplicate=True, reindex=False): 79 ''' 80 Transform indexes in coupled or derived indexes (codec extension). 81 If derived option is True, self._codec is extended and idx codec not, 82 else, both are coupled and both codec are extended. 83 84 *Parameters* 85 86 - **idx** : single Field or list of Field to be coupled or derived. 87 - **derived** : boolean (default : True) - if True result is derived, 88 if False coupled 89 - **duplicate** : boolean (default: True) - if True, return duplicate records 90 (only for self index) 91 - **reindex** : boolean (default : False). If True self.index is reindexed 92 with default codec. But if not derived, idx indexes MUST to be reindexed. 93 94 *Returns* : tuple with duplicate records (errors) if 'duplicate', None else''' 95 if not isinstance(idx, list): 96 index = [idx] 97 else: 98 index = idx 99 idxzip = self.__class__(list(zip(*([self._keys] + [ix._keys for ix in index]))), 100 reindex=True) 101 self.tocoupled(idxzip) 102 if not derived: 103 for ind in index: 104 ind.tocoupled(idxzip) 105 if duplicate: 106 return self.getduplicates(reindex) 107 if reindex: 108 self.reindex() 109 return 110 111 def couplinginfos(self, other, default=False): 112 '''return a dict with the coupling info between other (distance, ratecpl, 113 rateder, dist, disttomin, disttomax, distmin, distmax, diff, typecoupl) 114 115 *Parameters* 116 117 - **other** : other index to compare 118 - **default** : comparison with default codec 119 120 *Returns* : dict''' 121 if default: 122 return util.couplinginfos(self.values, other.values) 123 if min(len(self), len(other)) == 0: 124 return {'dist': 0, 'rateder': 0, 'disttomin': 0, 'disttomax': 0, 125 'distmin': 0, 'distmax': 0, 'diff': 0, 'typecoupl': 'null', 126 'distance': 0, 'ratecpl': 0} 127 xs = len(self._codec) # xs 128 xo = len(other._codec) # xo 129 dmin = max(xs, xo) # dmin 130 dmax = xs * xo # dmax 131 diff = abs(xs - xo) # diff 132 if min(xs, xo) == 1: 133 ratecpl = 0 134 if dmax - dmin + diff != 0: 135 ratecpl = diff / (dmax - dmin + diff) # 136 if xs == 1: 137 typec = 'derived' 138 else: 139 typec = 'derive' 140 return {'dist': dmin, 'rateder': 0, 'disttomin': 0, 'disttomax': 0, 141 'distmin': dmin, 'distmax': dmax, 'diff': diff, 142 'typecoupl': typec, 'distance': diff, 'ratecpl': ratecpl} 143 xso = len(util.tocodec([tuple((v1, v2)) # xab 144 for v1, v2 in zip(self._keys, other._keys)])) 145 dic = {'dist': xso, 'distmin': dmin, 'distmax': dmax, 'diff': diff, 146 'rateder': (xso - dmin) / (dmax - dmin), # rateDer 147 'disttomin': xso - dmin, 148 'disttomax': dmax - xso, 149 'distance': xso - dmin + diff, 150 'ratecpl': (xso - dmin + diff) / (dmax - dmin + diff)} #rateCpl 151 if dic['rateder'] == 0 and dic['diff'] == 0: 152 dic['typecoupl'] = 'coupled' 153 elif dic['rateder'] == 0 and xs < xo: 154 dic['typecoupl'] = 'derived' 155 elif dic['rateder'] == 0 and xs > xo: 156 dic['typecoupl'] = 'derive' 157 elif dic['rateder'] == 1: 158 dic['typecoupl'] = 'crossed' 159 elif xs < xo: 160 dic['typecoupl'] = 'linked' 161 else: 162 dic['typecoupl'] = 'link' 163 return dic 164 165 def derkeys(self, parent): 166 '''return keys derived from parent keys 167 168 *Parameters* 169 170 - **parent** : Field - parent 171 172 *Returns* : list of keys''' 173 derkey = [ES.nullparent] * len(parent._codec) 174 for i in range(len(self)): 175 derkey[parent._keys[i]] = self._keys[i] 176 if min(derkey) < 0: 177 raise FieldError("parent is not a derive Field") 178 return derkey 179 180 def extendkeys(self, keys): 181 '''add keys to the Field 182 183 *Parameters* 184 185 - **keys** : list of int (value lower or equal than actual keys) 186 187 *Returns* : None ''' 188 if min(keys) < 0 or max(keys) > len(self._codec) - 1: 189 raise FieldError('keys not consistent with codec') 190 self._keys += keys 191 192 @staticmethod 193 def full(listidx): 194 '''tranform a list of indexes in crossed indexes (value extension). 195 196 *Parameters* 197 198 - **listidx** : list of Field to transform 199 200 *Returns* : tuple of records added ''' 201 idx1 = listidx[0] 202 for idx in listidx: 203 if len(idx) != len(idx): 204 return None 205 leninit = len(idx1) 206 keysadd = util.idxfull(listidx) 207 for idx, keys in zip(listidx, keysadd): 208 idx._keys += keys 209 return tuple(range(leninit, len(idx1))) 210 211 def getduplicates(self, reindex=False): 212 ''' calculate items with duplicate codec 213 214 *Parameters* 215 216 - **reindex** : boolean (default : False). If True index is reindexed with default codec 217 218 *Returns* : tuple of items with duplicate codec''' 219 count = Counter(self._codec) 220 defcodec = list(count - Counter(list(count))) 221 dkeys = defaultdict(list) 222 for key, ind in zip(self._keys, range(len(self))): 223 dkeys[key].append(ind) 224 dcodec = defaultdict(list) 225 for key, ind in zip(self._codec, range(len(self._codec))): 226 dcodec[key].append(ind) 227 duplicates = [] 228 for item in defcodec: 229 for codecitem in dcodec[item]: 230 duplicates += dkeys[codecitem] 231 if reindex: 232 self.reindex() 233 return tuple(duplicates) 234 235 def iscrossed(self, other): 236 '''return True if self is crossed to other''' 237 return self.couplinginfos(other)['rateder'] == 1.0 238 239 def iscoupled(self, other): 240 '''return True if self is coupled to other''' 241 info = self.couplinginfos(other) 242 return info['diff'] == 0 and info['rateder'] == 0 243 244 def isderived(self, other): 245 '''return True if self is derived from other''' 246 info = self.couplinginfos(other) 247 return info['diff'] != 0 and info['rateder'] == 0.0 248 249 def iskeysfromderkeys(self, other): 250 '''return True if self._keys is relative from other._keys''' 251 leng = len(other._codec) 252 if leng % len(self._codec) != 0: 253 return False 254 keys = [(i*len(self._codec))//leng for i in range(leng)] 255 return self.__class__.keysfromderkeys(other._keys, keys) == self._keys 256 257 def islinked(self, other): 258 '''return True if self is linked to other''' 259 rate = self.couplinginfos(other)['rateder'] 260 return 0.0 < rate < 1.0 261 262 def isvalue(self, value, extern=True): 263 ''' return True if value is in index values 264 265 *Parameters* 266 267 - **value** : value to check 268 - **extern** : if True, compare value to external representation of self.value, 269 else, internal''' 270 if extern: 271 return value in self.val 272 return value in self.values 273 274 def keytoval(self, key, extern=True): 275 ''' return the value of a key 276 277 *Parameters* 278 279 - **key** : key to convert into values 280 - **extern** : if True, return string representation else, internal value 281 282 *Returns* 283 284 - **int** : first key finded (None else)''' 285 if key < 0 or key >= len(self._codec): 286 return None 287 if extern: 288 return self.cod[key] 289 return self._codec[key] 290 291 @staticmethod 292 def keysfromderkeys(parentkeys, derkeys): 293 '''return keys from parent keys and derkeys 294 295 *Parameters* 296 297 - **parentkeys** : list of keys from parent 298 - **derkeys** : list of derived keys 299 300 *Returns* : list of keys''' 301 #return [derkeys[parentkeys[i]] for i in range(len(parentkeys))] 302 return [derkeys[pkey] for pkey in parentkeys] 303 304 def loc(self, value, extern=True): 305 '''return a list of record number with value 306 307 *Parameters* 308 309 - **value** : value to check 310 - **extern** : if True, compare value to external representation of self.value, 311 else, internal 312 313 *Returns* 314 315 - **list of int** : list of record number finded (None else)''' 316 return self.recordfromvalue(value, extern=extern) 317 318 def recordfromvalue(self, value, extern=True): 319 '''return a list of record number with value 320 321 *Parameters* 322 323 - **value** : value to check 324 - **extern** : if True, compare value to external representation of self.value, 325 else, internal 326 327 *Returns* 328 329 - **list of int** : list of record number finded (None else)''' 330 331 if extern: 332 value = self.s_to_i(value) 333 if not value in self._codec: 334 return None 335 listkeys = [cod for cod, val in zip( 336 range(len(self._codec)), self._codec) if val == value] 337 return self.recordfromkeys(listkeys) 338 339 def recordfromkeys(self, listkeys): 340 '''return a list of record number with key in listkeys 341 342 *Parameters* 343 344 - **listkeys** : list of keys to check 345 346 *Returns* 347 348 - **list of int** : list of record number finded (None else)''' 349 350 return [rec for rec, key in zip(range(len(self)), self._keys) if key in listkeys] 351 352 def reindex(self, codec=None): 353 '''apply a reordered codec. If None, a new default codec is apply. 354 355 *Parameters* 356 357 - **codec** : list (default None) - reordered codec to apply. 358 359 *Returns* : self''' 360 361 if not codec: 362 codec = util.tocodec(self.values) 363 self._keys = util.reindex(self._keys, self._codec, codec) 364 self._codec = codec 365 return self 366 367 def reorder(self, sort=None, inplace=True): 368 '''Change the Field order with a new order define by sort and reset the codec. 369 370 *Parameters* 371 372 - **sort** : int list (default None)- new record order to apply. If None, no change. 373 - **inplace** : boolean (default True) - if True, new order is apply to self, 374 if False a new Field is created. 375 376 *Returns* 377 378 - **Field** : self if inplace, new Field if not inplace''' 379 values = util.reorder(self.values, sort) 380 codec, keys = util.resetidx(values) 381 if inplace: 382 self._keys = keys 383 self._codec = codec 384 return None 385 return self.__class__(name=self.name, codec=codec, keys=keys) 386 387 def setcodecvalue(self, oldvalue, newvalue, extern=True, 388 nameonly=False, valueonly=False): 389 '''update all the oldvalue by newvalue 390 391 *Parameters* 392 393 - **oldvalue** : list of values to replace 394 - **newvalue** : list of new value to apply 395 - **extern** : if True, the newvalue has external representation, else internal 396 - **nameonly** : if True, only the name of ESValue is changed 397 - **valueonly** : if True, only the value of ESValue is changed 398 399 *Returns* : int - last codec rank updated (-1 if None)''' 400 if extern: 401 newvalue = self.s_to_i(newvalue) 402 oldvalue = self.s_to_i(oldvalue) 403 rank = -1 404 for i in range(len(self._codec)): 405 if self._codec[i] == oldvalue: 406 if nameonly: 407 self._codec[i].setName(newvalue.ntv_name) 408 elif valueonly: 409 self._codec[i].setValue(newvalue.ntv_value) 410 else: 411 self._codec[i] = newvalue 412 rank = i 413 return rank 414 415 def setcodeclist(self, listcodec, extern=True, nameonly=False, valueonly=False): 416 '''update codec with listcodec values 417 418 *Parameters* 419 420 - **listcodec** : list of new codec values to apply 421 - **extern** : if True, the newvalue has external representation, else internal 422 - **nameonly** : if True, only the name of ESValue is changed 423 - **valueonly** : if True, only the value of ESValue is changed 424 425 *Returns* : int - last codec rank updated (-1 if None)''' 426 if extern: 427 listcodec = self.l_to_i(listcodec) 428 self._codec = listcodec 429 430 def set_keys(self, keys): 431 ''' _keys setters ''' 432 self._keys = keys 433 434 def set_codec(self, codec): 435 ''' _codec setters ''' 436 self._codec = codec 437 438 def setkeys(self, keys, inplace=True): 439 '''apply new keys (replace codec with extended codec from parent keys) 440 441 *Parameters* 442 443 - **keys** : list of keys to apply 444 - **inplace** : if True, update self data, else create a new Field 445 446 *Returns* : self or new Field''' 447 codec = util.tocodec(self.values, keys) 448 if inplace: 449 self._codec = codec 450 self._keys = keys 451 return self 452 return self.__class__(codec=codec, name=self.name, keys=keys) 453 454 def setname(self, name): 455 '''update the Field name 456 457 *Parameters* 458 459 - **name** : str to set into name 460 461 *Returns* : boolean - True if update''' 462 if isinstance(name, str): 463 self.name = name 464 return True 465 return False 466 467 def setvalue(self, ind, value, extern=True, nameonly=False, valueonly=False): 468 '''update a value at the rank ind (and update codec and keys) 469 470 *Parameters* 471 472 - **ind** : rank of the value 473 - **value** : new value 474 - **extern** : if True, the value has external representation, else internal 475 - **nameonly** : if True, only the name of ESValue is changed 476 - **valueonly** : if True, only the value of ESValue is changed 477 478 *Returns* : None''' 479 if extern: 480 value = self.s_to_i(value) 481 values = self.values 482 if nameonly: 483 values[ind].setName(values.ntv_name) 484 elif valueonly: 485 values[ind].setValue(values.ntv_value) 486 else: 487 values[ind] = value 488 self._codec, self._keys = util.resetidx(values) 489 490 def setlistvalue(self, listvalue, extern=True, nameonly=False, valueonly=False): 491 '''update the values (and update codec and keys) 492 493 *Parameters* 494 495 - **listvalue** : list - list of new values 496 - **extern** : if True, the value has external representation, else internal 497 - **nameonly** : if True, only the name of ESValue is changed 498 - **valueonly** : if True, only the value of ESValue is changed 499 500 *Returns* : None''' 501 if extern: 502 listvalue = self.l_to_i(listvalue) 503 values = self.values 504 for i, value_i in enumerate(listvalue): 505 if nameonly: 506 values[i].setName(value_i.ntv_name) 507 elif valueonly: 508 values[i].setValue(value_i.ntv_value) 509 else: 510 values[i] = value_i 511 self._codec, self._keys = util.resetidx(values) 512 513 def sort(self, reverse=False, inplace=True, func=str): 514 '''Define sorted index with ordered codec. 515 516 *Parameters* 517 518 - **reverse** : boolean (defaut False) - codec is sorted with reverse order 519 - **inplace** : boolean (default True) - if True, new order is apply to self, 520 if False a new Field is created. 521 - **func** : function (default str) - key used in the sorted function 522 523 *Return* 524 525 - **Field** : self if inplace, new Field if not inplace''' 526 if inplace: 527 self.reindex(codec=sorted(self._codec, reverse=reverse, key=func)) 528 self._keys.sort() 529 return self 530 oldcodec = self._codec 531 codec = sorted(oldcodec, reverse=reverse, key=str) 532 return self.__class__(name=self.name, codec=codec, 533 keys=sorted(util.reindex(self._keys, oldcodec, codec))) 534 535 def tocoupled(self, other, coupling=True): 536 ''' 537 Transform a derived index in a coupled index (keys extension) and add 538 new values to have the same length as other. 539 540 *Parameters* 541 542 - **other** : index to be coupled. 543 - **coupling** : boolean (default True) - reindex if False 544 545 *Returns* : None''' 546 dic = util.idxlink(other._keys, self._keys) 547 if not dic: 548 raise FieldError("Field is not coupled or derived from other") 549 self._codec = [self._codec[dic[i]] for i in range(len(dic))] 550 self._keys = other._keys 551 if not coupling: 552 self.reindex() 553 554 def tostdcodec(self, inplace=False, full=True): 555 ''' 556 Transform codec in full or in default codec. 557 558 *Parameters* 559 560 - **inplace** : boolean (default True) - if True, new order is apply to self, 561 - **full** : boolean (default True) - if True reindex with full codec 562 563 *Return* 564 565 - **Field** : self if inplace, new Field if not inplace''' 566 if full: 567 codec = self.values 568 keys = list(range(len(codec))) 569 else: 570 codec = util.tocodec(self.values) 571 keys = util.reindex(self._keys, self._codec, codec) 572 if inplace: 573 self._codec = codec 574 self._keys = keys 575 return self 576 return self.__class__(codec=codec, name=self.name, keys=keys) 577 578 def valtokey(self, value, extern=True): 579 '''convert a value to a key 580 581 *Parameters* 582 583 - **value** : value to convert 584 - **extern** : if True, the value has external representation, else internal 585 586 *Returns* 587 588 - **int** : first key finded (None else)''' 589 if extern: 590 value = self.s_to_i(value) 591 if value in self._codec: 592 return self._codec.index(value) 593 return None
this class includes Field methods :
add - update methods
FieldStructure.appendFieldStructure.setcodecvalueFieldStructure.setcodeclistFieldStructure.setnameFieldStructure.setkeysFieldStructure.setlistvalueFieldStructure.setvalue
transform methods
FieldStructure.couplingFieldStructure.extendkeysFieldStructure.fullFieldStructure.reindexFieldStructure.reorderFieldStructure.sortFieldStructure.tocoupledFieldStructure.tostdcodec
getters methods
FieldStructure.couplinginfosFieldStructure.derkeysFieldStructure.getduplicatesFieldStructure.iscrossedFieldStructure.iscoupledFieldStructure.isderivedFieldStructure.islinkedFieldStructure.isvalueFieldStructure.iskeysfromderkeysFieldStructure.keysfromderkeysFieldStructure.keytovalFieldStructure.locFieldStructure.recordfromkeysFieldStructure.recordfromvalueFieldStructure.valtokey
59 def append(self, value, unique=True): 60 '''add a new value 61 62 *Parameters* 63 64 - **value** : new object value 65 - **unique** : boolean (default True) - If False, duplication codec if value is present 66 67 *Returns* : key of value ''' 68 #value = Ntv.obj(value) 69 value = self.s_to_i(value) 70 if value in self._codec and unique: 71 key = self._codec.index(value) 72 else: 73 key = len(self._codec) 74 self._codec.append(value) 75 self._keys.append(key) 76 return key
add a new value
Parameters
- value : new object value
- unique : boolean (default True) - If False, duplication codec if value is present
Returns : key of value
78 def coupling(self, idx, derived=True, duplicate=True, reindex=False): 79 ''' 80 Transform indexes in coupled or derived indexes (codec extension). 81 If derived option is True, self._codec is extended and idx codec not, 82 else, both are coupled and both codec are extended. 83 84 *Parameters* 85 86 - **idx** : single Field or list of Field to be coupled or derived. 87 - **derived** : boolean (default : True) - if True result is derived, 88 if False coupled 89 - **duplicate** : boolean (default: True) - if True, return duplicate records 90 (only for self index) 91 - **reindex** : boolean (default : False). If True self.index is reindexed 92 with default codec. But if not derived, idx indexes MUST to be reindexed. 93 94 *Returns* : tuple with duplicate records (errors) if 'duplicate', None else''' 95 if not isinstance(idx, list): 96 index = [idx] 97 else: 98 index = idx 99 idxzip = self.__class__(list(zip(*([self._keys] + [ix._keys for ix in index]))), 100 reindex=True) 101 self.tocoupled(idxzip) 102 if not derived: 103 for ind in index: 104 ind.tocoupled(idxzip) 105 if duplicate: 106 return self.getduplicates(reindex) 107 if reindex: 108 self.reindex() 109 return
Transform indexes in coupled or derived indexes (codec extension). If derived option is True, self._codec is extended and idx codec not, else, both are coupled and both codec are extended.
Parameters
- idx : single Field or list of Field to be coupled or derived.
- derived : boolean (default : True) - if True result is derived, if False coupled
- duplicate : boolean (default: True) - if True, return duplicate records (only for self index)
- reindex : boolean (default : False). If True self.index is reindexed with default codec. But if not derived, idx indexes MUST to be reindexed.
Returns : tuple with duplicate records (errors) if 'duplicate', None else
111 def couplinginfos(self, other, default=False): 112 '''return a dict with the coupling info between other (distance, ratecpl, 113 rateder, dist, disttomin, disttomax, distmin, distmax, diff, typecoupl) 114 115 *Parameters* 116 117 - **other** : other index to compare 118 - **default** : comparison with default codec 119 120 *Returns* : dict''' 121 if default: 122 return util.couplinginfos(self.values, other.values) 123 if min(len(self), len(other)) == 0: 124 return {'dist': 0, 'rateder': 0, 'disttomin': 0, 'disttomax': 0, 125 'distmin': 0, 'distmax': 0, 'diff': 0, 'typecoupl': 'null', 126 'distance': 0, 'ratecpl': 0} 127 xs = len(self._codec) # xs 128 xo = len(other._codec) # xo 129 dmin = max(xs, xo) # dmin 130 dmax = xs * xo # dmax 131 diff = abs(xs - xo) # diff 132 if min(xs, xo) == 1: 133 ratecpl = 0 134 if dmax - dmin + diff != 0: 135 ratecpl = diff / (dmax - dmin + diff) # 136 if xs == 1: 137 typec = 'derived' 138 else: 139 typec = 'derive' 140 return {'dist': dmin, 'rateder': 0, 'disttomin': 0, 'disttomax': 0, 141 'distmin': dmin, 'distmax': dmax, 'diff': diff, 142 'typecoupl': typec, 'distance': diff, 'ratecpl': ratecpl} 143 xso = len(util.tocodec([tuple((v1, v2)) # xab 144 for v1, v2 in zip(self._keys, other._keys)])) 145 dic = {'dist': xso, 'distmin': dmin, 'distmax': dmax, 'diff': diff, 146 'rateder': (xso - dmin) / (dmax - dmin), # rateDer 147 'disttomin': xso - dmin, 148 'disttomax': dmax - xso, 149 'distance': xso - dmin + diff, 150 'ratecpl': (xso - dmin + diff) / (dmax - dmin + diff)} #rateCpl 151 if dic['rateder'] == 0 and dic['diff'] == 0: 152 dic['typecoupl'] = 'coupled' 153 elif dic['rateder'] == 0 and xs < xo: 154 dic['typecoupl'] = 'derived' 155 elif dic['rateder'] == 0 and xs > xo: 156 dic['typecoupl'] = 'derive' 157 elif dic['rateder'] == 1: 158 dic['typecoupl'] = 'crossed' 159 elif xs < xo: 160 dic['typecoupl'] = 'linked' 161 else: 162 dic['typecoupl'] = 'link' 163 return dic
return a dict with the coupling info between other (distance, ratecpl, rateder, dist, disttomin, disttomax, distmin, distmax, diff, typecoupl)
Parameters
- other : other index to compare
- default : comparison with default codec
Returns : dict
165 def derkeys(self, parent): 166 '''return keys derived from parent keys 167 168 *Parameters* 169 170 - **parent** : Field - parent 171 172 *Returns* : list of keys''' 173 derkey = [ES.nullparent] * len(parent._codec) 174 for i in range(len(self)): 175 derkey[parent._keys[i]] = self._keys[i] 176 if min(derkey) < 0: 177 raise FieldError("parent is not a derive Field") 178 return derkey
return keys derived from parent keys
Parameters
- parent : Field - parent
Returns : list of keys
180 def extendkeys(self, keys): 181 '''add keys to the Field 182 183 *Parameters* 184 185 - **keys** : list of int (value lower or equal than actual keys) 186 187 *Returns* : None ''' 188 if min(keys) < 0 or max(keys) > len(self._codec) - 1: 189 raise FieldError('keys not consistent with codec') 190 self._keys += keys
add keys to the Field
Parameters
- keys : list of int (value lower or equal than actual keys)
Returns : None
192 @staticmethod 193 def full(listidx): 194 '''tranform a list of indexes in crossed indexes (value extension). 195 196 *Parameters* 197 198 - **listidx** : list of Field to transform 199 200 *Returns* : tuple of records added ''' 201 idx1 = listidx[0] 202 for idx in listidx: 203 if len(idx) != len(idx): 204 return None 205 leninit = len(idx1) 206 keysadd = util.idxfull(listidx) 207 for idx, keys in zip(listidx, keysadd): 208 idx._keys += keys 209 return tuple(range(leninit, len(idx1)))
tranform a list of indexes in crossed indexes (value extension).
Parameters
- listidx : list of Field to transform
Returns : tuple of records added
211 def getduplicates(self, reindex=False): 212 ''' calculate items with duplicate codec 213 214 *Parameters* 215 216 - **reindex** : boolean (default : False). If True index is reindexed with default codec 217 218 *Returns* : tuple of items with duplicate codec''' 219 count = Counter(self._codec) 220 defcodec = list(count - Counter(list(count))) 221 dkeys = defaultdict(list) 222 for key, ind in zip(self._keys, range(len(self))): 223 dkeys[key].append(ind) 224 dcodec = defaultdict(list) 225 for key, ind in zip(self._codec, range(len(self._codec))): 226 dcodec[key].append(ind) 227 duplicates = [] 228 for item in defcodec: 229 for codecitem in dcodec[item]: 230 duplicates += dkeys[codecitem] 231 if reindex: 232 self.reindex() 233 return tuple(duplicates)
calculate items with duplicate codec
Parameters
- reindex : boolean (default : False). If True index is reindexed with default codec
Returns : tuple of items with duplicate codec
235 def iscrossed(self, other): 236 '''return True if self is crossed to other''' 237 return self.couplinginfos(other)['rateder'] == 1.0
return True if self is crossed to other
239 def iscoupled(self, other): 240 '''return True if self is coupled to other''' 241 info = self.couplinginfos(other) 242 return info['diff'] == 0 and info['rateder'] == 0
return True if self is coupled to other
244 def isderived(self, other): 245 '''return True if self is derived from other''' 246 info = self.couplinginfos(other) 247 return info['diff'] != 0 and info['rateder'] == 0.0
return True if self is derived from other
249 def iskeysfromderkeys(self, other): 250 '''return True if self._keys is relative from other._keys''' 251 leng = len(other._codec) 252 if leng % len(self._codec) != 0: 253 return False 254 keys = [(i*len(self._codec))//leng for i in range(leng)] 255 return self.__class__.keysfromderkeys(other._keys, keys) == self._keys
return True if self._keys is relative from other._keys
257 def islinked(self, other): 258 '''return True if self is linked to other''' 259 rate = self.couplinginfos(other)['rateder'] 260 return 0.0 < rate < 1.0
return True if self is linked to other
262 def isvalue(self, value, extern=True): 263 ''' return True if value is in index values 264 265 *Parameters* 266 267 - **value** : value to check 268 - **extern** : if True, compare value to external representation of self.value, 269 else, internal''' 270 if extern: 271 return value in self.val 272 return value in self.values
return True if value is in index values
Parameters
- value : value to check
- extern : if True, compare value to external representation of self.value, else, internal
274 def keytoval(self, key, extern=True): 275 ''' return the value of a key 276 277 *Parameters* 278 279 - **key** : key to convert into values 280 - **extern** : if True, return string representation else, internal value 281 282 *Returns* 283 284 - **int** : first key finded (None else)''' 285 if key < 0 or key >= len(self._codec): 286 return None 287 if extern: 288 return self.cod[key] 289 return self._codec[key]
return the value of a key
Parameters
- key : key to convert into values
- extern : if True, return string representation else, internal value
Returns
- int : first key finded (None else)
291 @staticmethod 292 def keysfromderkeys(parentkeys, derkeys): 293 '''return keys from parent keys and derkeys 294 295 *Parameters* 296 297 - **parentkeys** : list of keys from parent 298 - **derkeys** : list of derived keys 299 300 *Returns* : list of keys''' 301 #return [derkeys[parentkeys[i]] for i in range(len(parentkeys))] 302 return [derkeys[pkey] for pkey in parentkeys]
return keys from parent keys and derkeys
Parameters
- parentkeys : list of keys from parent
- derkeys : list of derived keys
Returns : list of keys
304 def loc(self, value, extern=True): 305 '''return a list of record number with value 306 307 *Parameters* 308 309 - **value** : value to check 310 - **extern** : if True, compare value to external representation of self.value, 311 else, internal 312 313 *Returns* 314 315 - **list of int** : list of record number finded (None else)''' 316 return self.recordfromvalue(value, extern=extern)
return a list of record number with value
Parameters
- value : value to check
- extern : if True, compare value to external representation of self.value, else, internal
Returns
- list of int : list of record number finded (None else)
318 def recordfromvalue(self, value, extern=True): 319 '''return a list of record number with value 320 321 *Parameters* 322 323 - **value** : value to check 324 - **extern** : if True, compare value to external representation of self.value, 325 else, internal 326 327 *Returns* 328 329 - **list of int** : list of record number finded (None else)''' 330 331 if extern: 332 value = self.s_to_i(value) 333 if not value in self._codec: 334 return None 335 listkeys = [cod for cod, val in zip( 336 range(len(self._codec)), self._codec) if val == value] 337 return self.recordfromkeys(listkeys)
return a list of record number with value
Parameters
- value : value to check
- extern : if True, compare value to external representation of self.value, else, internal
Returns
- list of int : list of record number finded (None else)
339 def recordfromkeys(self, listkeys): 340 '''return a list of record number with key in listkeys 341 342 *Parameters* 343 344 - **listkeys** : list of keys to check 345 346 *Returns* 347 348 - **list of int** : list of record number finded (None else)''' 349 350 return [rec for rec, key in zip(range(len(self)), self._keys) if key in listkeys]
return a list of record number with key in listkeys
Parameters
- listkeys : list of keys to check
Returns
- list of int : list of record number finded (None else)
352 def reindex(self, codec=None): 353 '''apply a reordered codec. If None, a new default codec is apply. 354 355 *Parameters* 356 357 - **codec** : list (default None) - reordered codec to apply. 358 359 *Returns* : self''' 360 361 if not codec: 362 codec = util.tocodec(self.values) 363 self._keys = util.reindex(self._keys, self._codec, codec) 364 self._codec = codec 365 return self
apply a reordered codec. If None, a new default codec is apply.
Parameters
- codec : list (default None) - reordered codec to apply.
Returns : self
367 def reorder(self, sort=None, inplace=True): 368 '''Change the Field order with a new order define by sort and reset the codec. 369 370 *Parameters* 371 372 - **sort** : int list (default None)- new record order to apply. If None, no change. 373 - **inplace** : boolean (default True) - if True, new order is apply to self, 374 if False a new Field is created. 375 376 *Returns* 377 378 - **Field** : self if inplace, new Field if not inplace''' 379 values = util.reorder(self.values, sort) 380 codec, keys = util.resetidx(values) 381 if inplace: 382 self._keys = keys 383 self._codec = codec 384 return None 385 return self.__class__(name=self.name, codec=codec, keys=keys)
Change the Field order with a new order define by sort and reset the codec.
Parameters
- sort : int list (default None)- new record order to apply. If None, no change.
- inplace : boolean (default True) - if True, new order is apply to self, if False a new Field is created.
Returns
- Field : self if inplace, new Field if not inplace
387 def setcodecvalue(self, oldvalue, newvalue, extern=True, 388 nameonly=False, valueonly=False): 389 '''update all the oldvalue by newvalue 390 391 *Parameters* 392 393 - **oldvalue** : list of values to replace 394 - **newvalue** : list of new value to apply 395 - **extern** : if True, the newvalue has external representation, else internal 396 - **nameonly** : if True, only the name of ESValue is changed 397 - **valueonly** : if True, only the value of ESValue is changed 398 399 *Returns* : int - last codec rank updated (-1 if None)''' 400 if extern: 401 newvalue = self.s_to_i(newvalue) 402 oldvalue = self.s_to_i(oldvalue) 403 rank = -1 404 for i in range(len(self._codec)): 405 if self._codec[i] == oldvalue: 406 if nameonly: 407 self._codec[i].setName(newvalue.ntv_name) 408 elif valueonly: 409 self._codec[i].setValue(newvalue.ntv_value) 410 else: 411 self._codec[i] = newvalue 412 rank = i 413 return rank
update all the oldvalue by newvalue
Parameters
- oldvalue : list of values to replace
- newvalue : list of new value to apply
- extern : if True, the newvalue has external representation, else internal
- nameonly : if True, only the name of ESValue is changed
- valueonly : if True, only the value of ESValue is changed
Returns : int - last codec rank updated (-1 if None)
415 def setcodeclist(self, listcodec, extern=True, nameonly=False, valueonly=False): 416 '''update codec with listcodec values 417 418 *Parameters* 419 420 - **listcodec** : list of new codec values to apply 421 - **extern** : if True, the newvalue has external representation, else internal 422 - **nameonly** : if True, only the name of ESValue is changed 423 - **valueonly** : if True, only the value of ESValue is changed 424 425 *Returns* : int - last codec rank updated (-1 if None)''' 426 if extern: 427 listcodec = self.l_to_i(listcodec) 428 self._codec = listcodec
update codec with listcodec values
Parameters
- listcodec : list of new codec values to apply
- extern : if True, the newvalue has external representation, else internal
- nameonly : if True, only the name of ESValue is changed
- valueonly : if True, only the value of ESValue is changed
Returns : int - last codec rank updated (-1 if None)
438 def setkeys(self, keys, inplace=True): 439 '''apply new keys (replace codec with extended codec from parent keys) 440 441 *Parameters* 442 443 - **keys** : list of keys to apply 444 - **inplace** : if True, update self data, else create a new Field 445 446 *Returns* : self or new Field''' 447 codec = util.tocodec(self.values, keys) 448 if inplace: 449 self._codec = codec 450 self._keys = keys 451 return self 452 return self.__class__(codec=codec, name=self.name, keys=keys)
apply new keys (replace codec with extended codec from parent keys)
Parameters
- keys : list of keys to apply
- inplace : if True, update self data, else create a new Field
Returns : self or new Field
454 def setname(self, name): 455 '''update the Field name 456 457 *Parameters* 458 459 - **name** : str to set into name 460 461 *Returns* : boolean - True if update''' 462 if isinstance(name, str): 463 self.name = name 464 return True 465 return False
update the Field name
Parameters
- name : str to set into name
Returns : boolean - True if update
467 def setvalue(self, ind, value, extern=True, nameonly=False, valueonly=False): 468 '''update a value at the rank ind (and update codec and keys) 469 470 *Parameters* 471 472 - **ind** : rank of the value 473 - **value** : new value 474 - **extern** : if True, the value has external representation, else internal 475 - **nameonly** : if True, only the name of ESValue is changed 476 - **valueonly** : if True, only the value of ESValue is changed 477 478 *Returns* : None''' 479 if extern: 480 value = self.s_to_i(value) 481 values = self.values 482 if nameonly: 483 values[ind].setName(values.ntv_name) 484 elif valueonly: 485 values[ind].setValue(values.ntv_value) 486 else: 487 values[ind] = value 488 self._codec, self._keys = util.resetidx(values)
update a value at the rank ind (and update codec and keys)
Parameters
- ind : rank of the value
- value : new value
- extern : if True, the value has external representation, else internal
- nameonly : if True, only the name of ESValue is changed
- valueonly : if True, only the value of ESValue is changed
Returns : None
490 def setlistvalue(self, listvalue, extern=True, nameonly=False, valueonly=False): 491 '''update the values (and update codec and keys) 492 493 *Parameters* 494 495 - **listvalue** : list - list of new values 496 - **extern** : if True, the value has external representation, else internal 497 - **nameonly** : if True, only the name of ESValue is changed 498 - **valueonly** : if True, only the value of ESValue is changed 499 500 *Returns* : None''' 501 if extern: 502 listvalue = self.l_to_i(listvalue) 503 values = self.values 504 for i, value_i in enumerate(listvalue): 505 if nameonly: 506 values[i].setName(value_i.ntv_name) 507 elif valueonly: 508 values[i].setValue(value_i.ntv_value) 509 else: 510 values[i] = value_i 511 self._codec, self._keys = util.resetidx(values)
update the values (and update codec and keys)
Parameters
- listvalue : list - list of new values
- extern : if True, the value has external representation, else internal
- nameonly : if True, only the name of ESValue is changed
- valueonly : if True, only the value of ESValue is changed
Returns : None
513 def sort(self, reverse=False, inplace=True, func=str): 514 '''Define sorted index with ordered codec. 515 516 *Parameters* 517 518 - **reverse** : boolean (defaut False) - codec is sorted with reverse order 519 - **inplace** : boolean (default True) - if True, new order is apply to self, 520 if False a new Field is created. 521 - **func** : function (default str) - key used in the sorted function 522 523 *Return* 524 525 - **Field** : self if inplace, new Field if not inplace''' 526 if inplace: 527 self.reindex(codec=sorted(self._codec, reverse=reverse, key=func)) 528 self._keys.sort() 529 return self 530 oldcodec = self._codec 531 codec = sorted(oldcodec, reverse=reverse, key=str) 532 return self.__class__(name=self.name, codec=codec, 533 keys=sorted(util.reindex(self._keys, oldcodec, codec)))
Define sorted index with ordered codec.
Parameters
- reverse : boolean (defaut False) - codec is sorted with reverse order
- inplace : boolean (default True) - if True, new order is apply to self, if False a new Field is created.
- func : function (default str) - key used in the sorted function
Return
- Field : self if inplace, new Field if not inplace
535 def tocoupled(self, other, coupling=True): 536 ''' 537 Transform a derived index in a coupled index (keys extension) and add 538 new values to have the same length as other. 539 540 *Parameters* 541 542 - **other** : index to be coupled. 543 - **coupling** : boolean (default True) - reindex if False 544 545 *Returns* : None''' 546 dic = util.idxlink(other._keys, self._keys) 547 if not dic: 548 raise FieldError("Field is not coupled or derived from other") 549 self._codec = [self._codec[dic[i]] for i in range(len(dic))] 550 self._keys = other._keys 551 if not coupling: 552 self.reindex()
Transform a derived index in a coupled index (keys extension) and add new values to have the same length as other.
Parameters
- other : index to be coupled.
- coupling : boolean (default True) - reindex if False
Returns : None
554 def tostdcodec(self, inplace=False, full=True): 555 ''' 556 Transform codec in full or in default codec. 557 558 *Parameters* 559 560 - **inplace** : boolean (default True) - if True, new order is apply to self, 561 - **full** : boolean (default True) - if True reindex with full codec 562 563 *Return* 564 565 - **Field** : self if inplace, new Field if not inplace''' 566 if full: 567 codec = self.values 568 keys = list(range(len(codec))) 569 else: 570 codec = util.tocodec(self.values) 571 keys = util.reindex(self._keys, self._codec, codec) 572 if inplace: 573 self._codec = codec 574 self._keys = keys 575 return self 576 return self.__class__(codec=codec, name=self.name, keys=keys)
Transform codec in full or in default codec.
Parameters
- inplace : boolean (default True) - if True, new order is apply to self,
- full : boolean (default True) - if True reindex with full codec
Return
- Field : self if inplace, new Field if not inplace
578 def valtokey(self, value, extern=True): 579 '''convert a value to a key 580 581 *Parameters* 582 583 - **value** : value to convert 584 - **extern** : if True, the value has external representation, else internal 585 586 *Returns* 587 588 - **int** : first key finded (None else)''' 589 if extern: 590 value = self.s_to_i(value) 591 if value in self._codec: 592 return self._codec.index(value) 593 return None
convert a value to a key
Parameters
- value : value to convert
- extern : if True, the value has external representation, else internal
Returns
- int : first key finded (None else)