Python中的二維矩陣“相減”——答東小羊問

問題描述:

在一個(gè) 220*2 的矩陣 A 中,以行為單位(即每行),行與行之間不存在重復(fù)的數(shù)據(jù)。現(xiàn)已經(jīng)得到了矩陣 A 中的 i 行數(shù)據(jù)構(gòu)成的矩陣 B,求另外 220-i 行數(shù)據(jù)構(gòu)成的矩陣 C 。

問題分析:
很明顯這個(gè)問題其實(shí)并不難,我們最容易想到的解決辦法就是for循環(huán),一個(gè)不行就兩個(gè),兩個(gè)不行就三個(gè)……但如果要求你盡可能少的使用for循環(huán)時(shí),這個(gè)問題又該如何處理呢?

本文實(shí)驗(yàn)環(huán)境:Python 3.6.1 |Anaconda 4.4.0 (64-bit)

方案1

拼接矩陣 + 虛數(shù)轉(zhuǎn)化 + 計(jì)數(shù)器

針對(duì)東小羊的這個(gè)具體的應(yīng)用場(chǎng)景,可以一個(gè)for循環(huán)也不使用。我們將B矩陣拼接在A矩陣的下方,得到拼接矩陣A_B,由于只有兩列數(shù)據(jù),所以我們借助虛數(shù)的概念,將每一行數(shù)據(jù)轉(zhuǎn)化為一個(gè)整體,再使用計(jì)數(shù)器判斷矩陣A_B中每個(gè)元素的個(gè)數(shù),其中個(gè)數(shù)為1的即是我們要尋找的數(shù)據(jù)。創(chuàng)建 get_others.py 代碼如下:

import numpy as np
from collections import Counter

mat = np.arange(20).reshape((10, 2))
sample_1 = np.arange(0, 6).reshape((3, 2))  # 測(cè)試樣例
############# 關(guān)鍵代碼開始 #############
con_mat = np.concatenate((mat, sample_1), axis=0)  # 拼接矩陣
x = con_mat[:, 0] + con_mat[:, 1] * 1j  # 利用虛數(shù)
res = np.array(list(Counter(x).values()))
sample_2 = mat[res == 1, :]
############# 關(guān)鍵代碼結(jié)束 #############
print("總的矩陣為:\n", mat)
print("第一部分為:\n", sample_1)
print("第二部分為:\n", sample_2)

上述代碼的缺陷在于,僅僅只適用于矩陣為兩列的情況,如何讓代碼的魯棒性更強(qiáng)呢。

方案2

拼接矩陣 + 元組轉(zhuǎn)化 + 計(jì)數(shù)器

·方案1 中的虛數(shù)轉(zhuǎn)化其實(shí)就是將一行數(shù)據(jù)變?yōu)橐粋€(gè)單元,那么同樣的我們可以將 get_others.py 中的虛數(shù)轉(zhuǎn)換部分改變?yōu)?tuple 即可,修改后的代碼如下:

import numpy as np
from collections import Counter

mat = np.arange(20).reshape((10, 2))
sample_1 = np.arange(0, 6).reshape((3, 2))  # 測(cè)試樣例
############# 關(guān)鍵代碼開始 #############
con_mat = np.concatenate((mat, sample_1), axis=0)  # 拼接矩陣
con_row_tuple = [tuple(t) for t in con_mat] # 將矩陣中的每一行轉(zhuǎn)換為tuple類型
res = np.array(list(Counter(con_row_tuple).values()))
sample_2 = mat[res == 1, :]
############# 關(guān)鍵代碼結(jié)束 #############
print("總的矩陣為:\n", mat)
print("第一部分為:\n", sample_1)
print("第二部分為:\n", sample_2)

方案3

元組轉(zhuǎn)化 + 集合運(yùn)算

在前面的基礎(chǔ)上,只要你明白了每一行為一個(gè)元素,那么引入集合來進(jìn)行減運(yùn)算也是非常容易理解的了。代碼如下:

import numpy as np

mat = np.arange(20).reshape((10, 2))
sample_1 = np.arange(0, 6).reshape((3, 2))  # 測(cè)試樣例
############# 關(guān)鍵代碼開始 #############
mat_tuple_set = set([tuple(t) for t in mat])  # 將矩陣中的每一行轉(zhuǎn)換為tuple類型并將結(jié)果轉(zhuǎn)為集合類型
sample_tuple_set = set([tuple(t) for t in sample_1])  # 將矩陣中的每一行轉(zhuǎn)換為tuple類型并將結(jié)果轉(zhuǎn)為集合類型
sample_2 = np.array([list(t) for t in (mat_tuple_set - sample_tuple_set)])  # 集合相減,再將結(jié)果轉(zhuǎn)換為二維矩陣形式
############# 關(guān)鍵代碼結(jié)束 #############
print("總的矩陣為:\n", mat)
print("第一部分為:\n", sample_1)
print("第二部分為:\n", sample_2)

利用集合來解決這個(gè)問題的思路是不錯(cuò)的,但主要在數(shù)據(jù)類型的轉(zhuǎn)換上花了較多時(shí)間。

總結(jié)

通過本文的描述,二維矩陣按行(列)去重或計(jì)數(shù)有了一定的解決辦法。去重和計(jì)數(shù)問題平常見得比較多的主要出現(xiàn)在一維的列表或數(shù)組中,通過借助 numpy.unique()collections.Counter() 或 轉(zhuǎn)換為 set 類型等等方法進(jìn)行解決。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,136評(píng)論 25 708
  • 《ilua》速成開發(fā)手冊(cè)3.0 官方用戶交流:iApp開發(fā)交流(1) 239547050iApp開發(fā)交流(2) 1...
    葉染柒丶閱讀 10,932評(píng)論 0 11
  • 手機(jī)的普及伴隨而來的是,越來越多各式各樣的App產(chǎn)品。選用正確實(shí)用的APP,可以簡(jiǎn)化生活,提高工作的效率。今天推薦...
    小二翻身做掌柜閱讀 1,622評(píng)論 9 15
  • 今天的晨讀有意思。 老生常談的排列組合,卻感覺多了許多新東西。 溫故而知新? 說說我看晨讀時(shí)候的心里路程。 001...
    李爹閱讀 244評(píng)論 9 7
  • 我們很多人都在一個(gè)房子里,實(shí)際上我們是不自由被關(guān)起來的,但由于人很多房子也比較大,并沒有人恐慌。在一個(gè)桌子上堆了很...
    kirakira閱讀 216評(píng)論 0 1