Python:* args unpacks,如何从test_train_split重新打包?

时间:2018-03-19 22:11:06

标签: python list dictionary scipy

我有多个(类型)输入放在列表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 个答案:

答案 0 :(得分:1)

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

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应用某种拆分,索引或切片,然后展平结果列表。

较新的Pythons有某种形式的*...解包,它将多个项目分配给变量。我没有太多使用它,所以必须查阅文档。但在这种情况下,我认为你想要收集一些列表中的所有其他值。我可以看到通过迭代和列表追加来做到这一点。使用一个列表理解即使不是不可能也很棘手,但是两个很好。

解包中的

'*'语法:

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]]

答案 1 :(得分:0)

这解决了 zigzag split 问题:

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)