我有以下代码,它采用 pandas 数据框的一列中的值,并将它们作为新数据框的列。数据框第一列中的值成为新数据框的索引。
从某种意义上说,我想把一个邻接表变成一个邻接矩阵。到目前为止,这是代码:
import pandas as pa
# Create a dataframe
oldcols = {'col1':['a','a','b','b'], 'col2':['c','d','c','d'], 'col3':[1,2,3,4]}
a = pa.DataFrame(oldcols)
# The columns of the new data frame will be the values in col2 of the original
newcols = list(set(oldcols['col2']))
rows = list(set(oldcols['col1']))
# Create the new data matrix
data = np.zeros((len(rows), len(newcols)))
# Iterate over each row and fill in the new matrix
for row in zip(a['col1'], a['col2'], a['col3']):
rowindex = rows.index(row[0])
colindex = newcols.index(row[1])
data[rowindex][colindex] = row[2]
newf = pa.DataFrame(data)
newf.columns = newcols
newf.index = rows
这适用于此特定实例,如下所示:原始 DataFrame
col1 col2 col3
0 a c 1
1 a d 2
2 b c 3
3 b d 4
被转换成一个新的 DataFrame 看起来像
c d
a 1 2
b 3 4
如果 col3 中的值不是数字,它将失败。我的问题是,是否有更优雅/更强大的方式来做到这一点?
这看起来像 pivot 的工作:
import pandas as pd
oldcols = {'col1':['a','a','b','b'], 'col2':['c','d','c','d'], 'col3':[1,2,3,4]}
a = pd.DataFrame(oldcols)
newf = a.pivot(index='col1', columns='col2')
print(newf)
产量
col3
col2 c d
col1
a 1 2
b 3 4
如果您不想要 MultiIndex 列,您可以使用以下方法删除
col3
:
newf.columns = newf.columns.droplevel(0)
然后会产生
col2 c d
col1
a 1 2
b 3 4
正如@unutbu 提到的,您可以使用
pivot
重塑数据框。
res = a.pivot(index='col1', columns='col2', values='col3')
更简洁的方法是将列标签解包为 args。
res = a.pivot(*a).rename_axis(index=None, columns=None)
另一种方法是显式构造图对象(使用流行的图库
networkx
)并构造邻接矩阵。对于简单的数据透视操作来说,它可能过于冗长,但如果给定的数据已经是图表形式,它可能会有用。
import networkx as nx
g = nx.Graph()
col1 = a['col1'].unique()
col2 = a['col2'].unique()
g.add_weighted_edges_from(list(map(tuple, a.values)))
res = nx.to_pandas_adjacency(g).loc[col1, col2]
另一种方法是将前两列分配为 MultiIndex,然后取消堆叠第二列:
df = pd.DataFrame({'col1':['a','a','b','b'], 'col2':['c','d','c','d'], 'col3':[1,2,3,4]})
df.set_index(['col1', 'col2']).squeeze().unstack('col2')
结果
col2 c d
col1
a 1 2
b 3 4
squeeze()
方法将具有单列的DataFrame转换为Series。