如何在不使用熊猫的情况下更改列的位置

时间:2018-12-28 10:53:20

标签: python arrays python-3.x matrix

我有一个如下所示的矩阵;

matrix="""  8 1 A A A A 8
            8 5 A A A 3 8
            7 2 A A 1 4 7
            6 1 3 A 2 5 7
            2 4 5 A 1 1 1"""

这是我的代码块:

lines= [i.strip().split() for i in matrix.splitlines()]
lst=[[lines[i][j] for i in range(len(lines))]for j in range(len(lines[0]))]
h=0
while h<=len(lines[0]):
    for i in range(len(lines[0])-1,0,-1):
        for j in range(len(lines)-1,-1,-1):
            for k in lst:
                if k.count('A')==len(lines):
                    if lines[j][i-1]=='A':
                        lines[j][i-1]=lines[j][i]
                        lines[j][i]='A'
    h+=1
for line in lines:
    print(*(i or " " for i in line) , sep=" ")

如果一列充满A,我想将该列移到最右边,但是我的代码将所有A移到右边。这是我的输出:

8 1 8 A A A A
8 5 3 8 A A A
7 2 1 4 7 A A
6 1 3 2 5 7 A
2 4 5 1 1 1 A

我想要这样的输出:

8 1 A A A 8 A
8 5 A A 3 8 A
7 2 A 1 4 7 A
6 1 3 2 5 7 A
2 4 5 1 1 1 A 

3 个答案:

答案 0 :(得分:6)

您可以use zip()来转置矩阵,将所有纯"A"排序到其末端,然后再次用zip()进行逆转置:

matrix="""  8 1 A A A A 8
            8 5 A A A 3 8
            7 2 A A 1 4 7
            6 1 3 A 2 5 7
            2 4 5 A 1 1 1"""

# string to list of lists of strings
m = [[x.strip() for x in line.split()] for line in matrix.split("\n")]
print(*m,sep="\n")

# transpose and sort
t_m = [list(line) for line in zip(*m)]
t_m.sort(key = lambda x: all(k=="A" for k in x))

# reverse transpose
m = [list(line) for line in zip(*t_m)]
print(*m,sep="\n")

输出:

# before
['8', '1', 'A', 'A', 'A', 'A', '8']
['8', '5', 'A', 'A', 'A', '3', '8']
['7', '2', 'A', 'A', '1', '4', '7']
['6', '1', '3', 'A', '2', '5', '7']
['2', '4', '5', 'A', '1', '1', '1']

# after
['8', '1', 'A', 'A', 'A', '8', 'A']
['8', '5', 'A', 'A', '3', '8', 'A']
['7', '2', 'A', '1', '4', '7', 'A']
['6', '1', '3', '2', '5', '7', 'A']
['2', '4', '5', '1', '1', '1', 'A']

转置后的数据如下:

# before sorting
['8', '8', '7', '6', '2']
['1', '5', '2', '1', '4']
['A', 'A', 'A', '3', '5']
['A', 'A', 'A', 'A', 'A']  # this is the column you want to sort behind all others
['A', 'A', '1', '2', '1']
['A', '3', '4', '5', '1']
['8', '8', '7', '7', '1']

# after sort
['8', '8', '7', '6', '2']
['1', '5', '2', '1', '4']
['A', 'A', 'A', '3', '5']
['A', 'A', '1', '2', '1']
['A', '3', '4', '5', '1']
['8', '8', '7', '7', '1']
['A', 'A', 'A', 'A', 'A']  # now it is here

sort/sorting之所以起作用,是因为如果整个行都由True'A')组成,而所有其他行都是True == 1,那么它只有False == 0

排序是稳定,因此它不会更改评估False的行之间的相对顺序。

答案 1 :(得分:3)

首先,让我们定义用于转置类似列表的实用工具功能

def transpose(elements):
    return list(map(list, zip(*elements)))

然后根据规则定义排序键:如果列表元素等于'A',则它排在最后,否则将其保持在原始位置

def sorting_key(indexed_row):
    return all(element == 'A' for element in indexed_row[1]), indexed_row

之后,我们的解决方案将是

>>> from operator import itemgetter
>>> transpose(map(itemgetter(1), sorted(enumerate(transpose(lines)),
                                        key=sorting_key)))

这给了我们

[['8', '1', 'A', 'A', 'A', '8', 'A'],
 ['8', '5', 'A', 'A', '3', '8', 'A'],
 ['7', '2', 'A', '1', '4', '7', 'A'],
 ['6', '1', '3', '2', '5', '7', 'A'],
 ['2', '4', '5', '1', '1', '1', 'A']]

或@PatrickArtner指出,sorted使用Timsort,即stable algorithm,因此我们不需要处理非全“ A”列的情况在其原始位置并定义:

def sorting_key(row):
    return all(element == 'A' for element in row)

在那之后我们可以简单地写

>>> transpose(sorted(transpose(lines),
                     key=sorting_key))

答案 2 :(得分:3)

这是使用numpy的一种方式:

s = np.array([x.strip() for x in matrix.split()]).reshape(5,7)
print(s)

array[['8', '1', 'A', 'A', 'A', 'A', '8'],
     ['8', '5', 'A', 'A', 'A', '3', '8'],
     ['7', '2', 'A', 'A', '1', '4', '7'],
     ['6', '1', '3', 'A', '2', '5', '7'],
     ['2', '4', '5', 'A', '1', '1', '1']]

您可以使用np.flatnonzero来找到all值为0的列,并用最后一个交换它们:

m = np.flatnonzero((s == 'A').all(axis=0))[0]
s.T[[m, s.shape[1]-1]] = s.T[[s.shape[1]-1, m]]

array([['8', '1', 'A', '8', 'A', 'A', 'A'],
       ['8', '5', 'A', '8', 'A', '3', 'A'],
       ['7', '2', 'A', '7', '1', '4', 'A'],
       ['6', '1', '3', '7', '2', '5', 'A'],
       ['2', '4', '5', '1', '1', '1', 'A']], dtype='<U21')