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

2024-10-01 11:40:34 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个矩阵如下所示

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 

Tags: 代码inforleniflinerange矩阵
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']]

您可以使用^{}来定位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')

首先,让我们定义一个实用函数来转置列表列表,比如

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,所以我们不需要处理case,将非all-“A”列保留在它们原来的位置并定义:

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

之后我们就可以简单地写了

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

您可以use ^{}将矩阵转置,将所有纯"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的行之间的相对顺序。你知道吗

相关问题 更多 >