我有一个像这样的熊猫数据框:
df = pd.DataFrame({'A':[1,3,2,9],'B':[2,1,2,7],'C':[7,2,4,6],'D':[8,1,6,4]},index=['A','B','C','D'])
>> A B C D
A 1 2 7 8
B 3 1 2 1
C 2 2 4 6
D 9 7 6 4
我想将此数据帧与相应的值更改为成对的,像这样:
>> col1 col2 val
A A 1
A B 3
A C 2
A D 9
... ... ...
D C 6
D D 4
一种方法是使用循环,但是对于非常大的数据帧,这将非常慢。有一些问题问到哪个解决了类似的问题,但是对于R。我猜一种方法是将数据帧转换为numpy矩阵,然后使用堆栈函数。但是我无法从中创建一个m×3的阵列。有人可以帮忙吗?
答案 0 :(得分:2)
将DataFrame.stack
与Series.reset_index
一起使用:
df = df.stack().reset_index()
df.columns = ['col1','col2','val']
或者使用numpy.repeat
,numpy.tile
和ravel
的numpy解决方案:
a = np.repeat(df.index, len(df.columns))
b = np.tile(df.columns, len(df))
c = df.values.ravel()
df = pd.DataFrame({'col1':a,'col2':b,'val':c})
print (df)
col1 col2 val
0 A A 1
1 A B 2
2 A C 7
3 A D 8
4 B A 3
5 B B 1
6 B C 2
7 B D 1
8 C A 2
9 C B 2
10 C C 4
11 C D 6
12 D A 9
13 D B 7
14 D C 6
15 D D 4
val
列与melt
和DataFrame.reset_index
的顺序不同的解决方案,对于列的相同顺序,请添加reindex
:
df = (df.rename_axis('col2')
.reset_index()
.melt('col2', var_name='col1', value_name='val')
.reindex(columns=['col1','col2','val']))
a = np.repeat(df.columns, len(df.columns))
b = np.tile(df.index, len(df))
c = df.values.T.ravel()
df1 = pd.DataFrame({'col1':a,'col2':b,'val':c})
print (df)
col1 col2 val
0 A A 1
1 A B 3
2 A C 2
3 A D 9
4 B A 2
5 B B 1
6 B C 2
7 B D 7
8 C A 7
9 C B 2
10 C C 4
11 C D 6
12 D A 8
13 D B 1
14 D C 6
15 D D 4
答案 1 :(得分:2)
类似于jezrael的答案之一。区别在于我创建了整数索引以进行切片。这使我可以切片二维数组df.values
而不是ravel
。这是一个口味/喜好问题。
n, m = df.shape
i = np.tile(np.arange(n), m)
j = np.arange(m).repeat(n)
pd.DataFrame(dict(
col1=df.columns[j],
col2=df.index[i],
val=df.values[i, j]
))
col1 col2 val
0 A A 1
1 A B 3
2 A C 2
3 A D 9
4 B A 2
5 B B 1
6 B C 2
7 B D 7
8 C A 7
9 C B 2
10 C C 4
11 C D 6
12 D A 8
13 D B 1
14 D C 6
15 D D 4