以特定方式重塑 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 方法要快得多
考虑以下代码:
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 方法要快得多