以特定方式重塑 pandas 数据框

Reshaping a pandas dataframe in a specific manner

考虑以下代码:

import pandas as pd

d = {'col1': [1, 2, 3 ,4 ,5, 5, 6, 5], 'col2': [3, 4, 3 ,4 , 5, 6 , 6, 5], 'col3': [5, 6, 3 ,4 , 5, 6 ,6, 5], 'col4': [7, 8, 3 , 4 , 5, 4 , 6, 4], }

df = pd.DataFrame(data=d)

df=df.T

此代码给出以下输出:

#       0  1  2  3  4  5  6  7
# col1  1  2  3  4  5  5  6  5
# col2  3  4  3  4  5  6  6  5
# col3  5  6  3  4  5  6  6  5
# col4  7  8  3  4  5  4  6  4

我想以如下所示重新排列列的方式重塑数据框:

#       0  1  
# col1  1  2  
# col2  3  4  
# col3  5  6  
# col4  7  8  
# col1  3  4  
# col2  3  4  
# col3  3  4  
# col4  3  4  
# col1  5  5 
# col2  5  6  
# col3  5  6  
# col4  5  4  
# col1  6  5
# col2  6  5
# col3  6  5
# col4  6  4

代码应该留有一定的修改空间,可以像上面的例子那样选择两列或者三列或者四列等等。有什么想法可以实现吗?

试试这个:

import pandas as pd

d = {'col1': [1, 2, 3 ,4 ,5, 5, 6, 5], 'col2': [3, 4, 3 ,4 , 5, 6 , 6, 5], 'col3': [5, 6, 3 ,4 , 5, 6 ,6, 5], 'col4': [7, 8, 3 , 4 , 5, 4 , 6, 4], }

df = pd.DataFrame(data=d)
df = df.T
number = 2    #Here you can choose the number of columns
df1 = df.iloc[:, :number]
for x in range(0, len(df.columns), number):
    df1 = pd.concat([df1, df.iloc[:, x:x + number].T.reset_index(drop=True).T])
print(df1)

一种更快的方法是使用 numpy,尤其是当列数为偶数时。

您正在重塑一个 2 列数据框;这是通过 np.reshape:

实现的
data = np.reshape(df.to_numpy(), (-1, 2))

data
array([[1, 2],
       [3, 4],
       [5, 5],
       [6, 5],
       [3, 4],
       [3, 4],
       [5, 6],
       [6, 5],
       [5, 6],
       [3, 4],
       [5, 6],
       [6, 5],
       [7, 8],
       [3, 4],
       [5, 4],
       [6, 4]])

当前索引的长度为4;重塑后,它应该是 length of current index * length of columns/2:

 index = np.tile(df.index, df.columns.size//2)
index
array(['col1', 'col2', 'col3', 'col4', 'col1', 'col2', 'col3', 'col4',
       'col1', 'col2', 'col3', 'col4', 'col1', 'col2', 'col3', 'col4'],
      dtype=object)

剩下的就是创建一个新的数据框:

pd.DataFrame(data, index = index)

      0  1
col1  1  2
col2  3  4
col3  5  5
col4  6  5
col1  3  4
col2  3  4
col3  5  6
col4  6  5
col1  5  6
col2  3  4
col3  5  6
col4  6  5
col1  7  8
col2  3  4
col3  5  4
col4  6  4

另一种选择,是使用偶数行和奇数行的思想来重塑数据,具有pyjanitor's pivot_longer功能;将 even(0) 和 odd(1) 整理到单独的列中:

# pip install git+https://github.com/pyjanitor-devs/pyjanitor.git
import pandas as pd
import janitor

(df.set_axis((df.columns % 2).astype(str), axis=1)
   .pivot_longer(ignore_index=False, 
                 names_to = ['0', '1'], 
                 names_pattern=['0', '1'])
)
      0  1
col1  1  2
col2  3  4
col3  5  6
col4  7  8
col1  3  4
col2  3  4
col3  3  4
col4  3  4
col1  5  5
col2  5  6
col3  5  6
col4  5  4
col1  6  5
col2  6  5
col3  6  5
col4  6  4

同样,numpy 方法要快得多