代码之家  ›  专栏  ›  技术社区  ›  Saravanabalagi Ramachandran

Python:*args解包,如何从test\u train\u split重新打包?

  •  0
  • Saravanabalagi Ramachandran  · 技术社区  · 8 年前

    我有多个(类型)输入放在列表中 x 我正在做 test train split 使用:

    x = [some_matrix, scalar_value, something_else, ...]
    x0_train, x0_test, x1_train, x1_test, ... , y_train, y_test = 
       train_test_split(x[0],x[1],... , y, test_size=0.2, random_state=np.random, shuffle=True)
    

    我设法改变了输入参数 x[0], x[1], ... 到 *x :

    x0_train, x0_test, x1_train, x1_test, ... , y_train, y_test = 
       train_test_split(*x, y, test_size=0.2, random_state=np.random, shuffle=True)
    
        # But I have to manually repack
        x_train = [x0_train, x1_train]
        x_test = [x0_test, x1_test]
    

    但是,有没有一种方法可以在不需要手动重新打包的情况下接收它?等效于:

    *x_train, *x_test, y_train, y_test = 
       train_test_split(*x, y, test_size=0.2, random_state=np.random, shuffle=True)
    

    还是有其他方法可以做到这一点?例如:构造一本字典并使用**解包,但我仍然有同样的问题。公约是什么(如果存在)?

    2 回复  |  直到 8 年前
        1
  •  1
  •   hpaulj    8 年前

    解包只是将列表、元组或其他iterable的元素分配给多个变量的一种方式。“重新打包”的常规方法是在列表(或元组)中收集这些变量:

    In [48]: a,b,c = [[1,2,3],3,[4,5]]
    In [49]: a
    Out[49]: [1, 2, 3]
    In [50]: b
    Out[50]: 3
    In [51]: c
    Out[51]: [4, 5]
    In [52]: [a,b,c]
    Out[52]: [[1, 2, 3], 3, [4, 5]]
    

    这样做的成本最低,因为它只是Python在玩对象指针。没有大数据块的拷贝。

    我不熟悉 train_test_split 行动您的输入和输出表明

    alist = [(x[mask], x[~mask]) for x in xinput]
    alist = itertools.chain(*alist)
    

    也就是说,它对每个输入应用某种拆分、索引或切片 *args ,然后展平结果列表。

    较新的蟒蛇有某种形式的 * 或 ... 解包,将多个项目分配给一个变量。我没怎么用过,所以得查一下文档。但在这种情况下,我认为您需要收集某个列表中的所有其他值。我可以看到通过迭代和列表附件来实现这一点。如果不是不可能的话,使用一个列表理解是很棘手的,但使用两个列表理解是可以的。

    解包中的“*”语法:

    In [55]: a, *b = [[1,2,3],3,[4,5]]
    In [56]: a
    Out[56]: [1, 2, 3]
    In [57]: b
    Out[57]: [3, [4, 5]]
    In [58]: [a,b]
    Out[58]: [[1, 2, 3], [3, [4, 5]]]
    In [59]: [a,*b]
    Out[59]: [[1, 2, 3], 3, [4, 5]]
    

    作业中不能有2个(或更多)带星号的表达式。


    受您对列表理解的启发,以下是收集列表中其他项目的另一种方法:

    In [65]: *a, = [1,2,3],[4,5],[10,11,12],[13,14]
    In [66]: a
    Out[66]: [[1, 2, 3], [4, 5], [10, 11, 12], [13, 14]]
    In [67]: a[::2]
    Out[67]: [[1, 2, 3], [10, 11, 12]]
    In [68]: a[1::2]
    Out[68]: [[4, 5], [13, 14]]
    
        2
  •  0
  •   Saravanabalagi Ramachandran    8 年前

    这解决了 锯齿形拆分 问题:

    recv = [None for i in range(2*len(x))]
    *recv, y_train, y_test = train_test_split(*x, y, test_size=0.2, random_state=np.random, shuffle=True)
    
    # Edit: credits hpaulj
    x_train = recv[::2]
    x_test = recv[1::2]
    

    此外,如果有办法复制引用,也可以

    x_train = [ None for _ in range(len(x))]
    x_test = [ None for _ in range(len(x))]
    
    recv = [item for sublist in zip(x_train, x_test) for item in sublist]
    # But unfortunately the above line gives only the values and not references
    # Hence doesn't work
    
    *recv, y_train, y_test = train_test_split(*x, y, test_size=0.2, random_state=np.random, shuffle=True)