У меня есть фрейм данных, в котором хранится информация о четырех субъектах A, B, C, D.
df = pd.DataFrame({
'subject': ['A', 'B', 'C', 'D'],
'X1': [80, 90, 70, 60],
'Y1': [10, 25, 20, 15],
'X2': [63, 75, 84, 92],
'Y2': [13, 28, 25, 18],
'X3': [36, 78, 64, 82],
'Y3': [18, 25, 24, 16]
})
print(df)
Из приведенного выше фрейма данных я хочу создать 4 фрейма данных df_A, df_B, df_C и df_D так, чтобы новый фрейм данных имел x1, y1 в качестве первой строки, x2, y2 в качестве второй и x3, y3 в качестве третьей.
Ожидаемые кадры выходных данных:
df_A = pd.DataFrame({
'X': [80, 63, 36],
'Y': [10, 13, 18]
})
print(df_A)
df_B = pd.DataFrame({
'X': [90, 75, 78],
'Y': [25, 28, 25]
})
print(df_B)
df_C = pd.DataFrame({
'X': [70, 84, 64],
'Y': [20, 25, 24]
})
print(df_C)
df_D = pd.DataFrame({
'X': [60, 92, 82],
'Y': [15, 18, 16]
})
print(df_D)
Как мне этого добиться? Я пробовал с iloc, но не получилось.
Возможное решение, которое перебирает строки фрейма данных и получает все значения X
и Y
значения соответственно из каждой строки:
[pd.DataFrame({
'X': y.iloc[1::2].to_list(),
'Y': y.iloc[2::2].to_list()})
for _, y in df.iterrows()]
В качестве альтернативы можно использовать np.reshape для удобного изменения значений фрейма данных, а затем вертикально разбить полученный массив (с помощью np.vsplit), чтобы получить 4 фрейма данных:
n = 4
a = df.drop('subject', axis=1).values.reshape(-1, 2)
[pd.DataFrame(x, columns=['X', 'Y']) for x in np.vsplit(a, n)]
Выход:
[ X Y
0 80 10
1 63 13
2 36 18,
X Y
0 90 25
1 75 28
2 78 25,
X Y
0 70 20
1 84 25
2 64 24,
X Y
0 60 15
1 92 18
2 82 16]
вы можете использовать wide_to_long()
с groupby()
вот так:
df = pd.DataFrame({
'subject': ['A', 'B', 'C', 'D'],
'X1': [80, 90, 70, 60],
'Y1': [10, 25, 20, 15],
'X2': [63, 75, 84, 92],
'Y2': [13, 28, 25, 18],
'X3': [36, 78, 64, 82],
'Y3': [18, 25, 24, 16]
})
df_long = pd.wide_to_long(df, stubnames=['X', 'Y'], i='subject', j='num', sep='').reset_index()
subject num X Y
0 A 1 80 10
1 B 1 90 25
2 C 1 70 20
3 D 1 60 15
4 A 2 63 13
5 B 2 75 28
6 C 2 84 25
7 D 2 92 18
8 A 3 36 18
9 B 3 78 25
10 C 3 64 24
11 D 3 82 16
df_list = [group.drop(columns=['subject', 'num']).reset_index(drop=True) for _, group in df_long.groupby('subject')]
for df in df_list:
print(df)
X Y
0 80 10
1 63 13
2 36 18
X Y
0 90 25
1 75 28
2 78 25
X Y
0 70 20
1 84 25
2 64 24
X Y
0 60 15
1 92 18
2 82 16
это сработало. Спасибо