从键值对列表中创建矩阵

4

我有一个包含字符串名称-值对的numpy数组列表。列表中每个名称和值都可能出现多次,我想将其转换为二进制矩阵。

列代表值,行代表键/名称,当一个字段设置为1时,表示特定的名称值对。

例如:

我有

A : aa
A : bb
A : cc
B : bb
C : aa

我想将它转换为:

并且我希望将其转化为


     aa bb cc 
 A    1  1  1
 B    0  1  0 
 C    1  0  0 

我有一些代码可以做到这一点,但我想知道是否有更简单/开箱即用的方法使用numpy或其他库来完成这个任务。

目前我的代码是这样的:

resources = Set(result[:,1])
resourcesDict = {}
i = 0 
for r in resources:   
    resourcesDict[r] = i
    i = i + 1

clients = Set(result[:,0])
clientsDict = {}
i = 0 
for c in clients:    
    clientsDict[c] = i
    i = i + 1

arr = np.zeros((len(clientsDict),len(resourcesDict)), dtype = 'bool')
for line in result[:,0:2]: 
    arr[clientsDict[line[0]],resourcesDict[line[1]]] = True

而结果中有以下内容
array([["a","aa"],["a","bb"],..]

1
没有看到你已经有的代码,无法回答你的问题。 - John
2
精确的输入格式是什么?您是否想将稀疏矩阵转换为密集矩阵?(然后请参见http://docs.scipy.org/doc/scipy/reference/generated/scipy.sparse.dok_matrix.html) - Piotr Migdal
请展示能够“做这件事”的代码。 - Ryan Saxe
4个回答

2

我认为使用Pandas.DataFrame.pivot是最好的方法。

>>> df = pd.DataFrame({'foo': ['one','one','one','two','two','two'],
                       'bar': ['A', 'B', 'C', 'A', 'B', 'C'],
                       'baz': [1, 2, 3, 4, 5, 6]})
>>> df
    foo   bar  baz
0   one   A    1
1   one   B    2
2   one   C    3
3   two   A    4
4   two   B    5
5   two   C    6

或者您可以使用以下方式加载您的配对列表:

>>> df = pd.read_csv('ratings.csv')

那么

>>> df.pivot(index='foo', columns='bar', values='baz')
     A   B   C
one  1   2   3
two  4   5   6

1
你可能有类似以下的东西
m_dict = {'A': ['aa', 'bb', 'cc'], 'B': ['bb'], 'C': ['aa']}

我会这样做:

res = {}
for k, v in m_dict.items():
    res[k] = defaultdict(int)
    for col in v:
        res[k][v] = 1

编辑

根据您的格式,可能更符合以下方式:

m_array = [['A', 'aa'], ['A', 'bb'], ['A', 'cc'], ['B', 'bb'], ['C', 'aa']]

res = defaultdict(lambda: defaultdict(int))
for k, v in m_array:
    res[k][v] = 1

两者都给出:

>>> res['A']['aa']
1
>>> res['B']['aa']
0

1
这是一个 np.unique 的工作。不清楚你的数据格式是什么,但你需要获得两个一维数组,一个包含键,另一个包含值,例如:
kvp = np.array([['A', 'aa'], ['A', 'bb'], ['A', 'cc'],
                ['B', 'bb'], ['C', 'aa']])

keys, values = kvp.T

rows, row_idx = np.unique(keys, return_inverse=True)
cols, col_idx = np.unique(values, return_inverse=True)

out = np.zeros((len(rows), len(cols)), dtype=np.int)
out[row_idx, col_idx] += 1

>>> out
array([[1, 1, 1],
       [0, 1, 0],
       [1, 0, 0]])
>>> rows
array(['A', 'B', 'C'], 
      dtype='|S2')
>>> cols
array(['aa', 'bb', 'cc'], 
      dtype='|S2')

如果没有重复的键值对,这段代码将正常工作。如果存在重复,我建议滥用scipy的稀疏模块:
import scipy.sparse as sps

kvp = np.array([['A', 'aa'], ['A', 'bb'], ['A', 'cc'],
                ['B', 'bb'], ['C', 'aa'], ['A', 'bb']])

keys, values = kvp.T

rows, row_idx = np.unique(keys, return_inverse=True)
cols, col_idx = np.unique(values, return_inverse=True)

out = sps.coo_matrix((np.ones_like(row_idx), (row_idx, col_idx))).A

>>> out
array([[1, 2, 1],
       [0, 1, 0],
       [1, 0, 0]])

0
d = {'A': ['aa', 'bb', 'cc'], 'C': ['aa'], 'B': ['bb']}
rows = 'ABC'
cols = ('aa', 'bb', 'cc')
print '   ', ' '.join(cols)
for row in rows:
    print row, ' ',
    for col in cols:
            print ' 1' if col in d.get(row) else ' 0',
    print

>>>     aa bb cc
>>> A    1  1  1
>>> B    0  1  0
>>> C    1  0  0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接