我试着用
当存在相同的值时,pivot_table取平均值(默认为aggfunc='mean'
)
例如:
d=pd.DataFrame(data={
'x_values':[13.4,13.08,12.73,12.,33.,23.,12.],
'y_values': [1.54, 1.47,1.,2.,4.,4.,3.],
'experiment':['e', 'e', 'e', 'f', 'f','f','f']})
print(pd.pivot_table(d, index='x_values',
columns='experiment', values='y_values',sort=False))
的回报:
experiment e f
x_values
13.40 1.54 NaN
13.08 1.47 NaN
12.73 1.00 NaN
12.00 NaN 2.5
33.00 NaN 4.0
23.00 NaN 4.0
可以看到f中出现了一个新值(2.5,即2的平均值)。和3)。
但是我想保持列表在pandas
中的样子experiment e f
x_values
13.40 1.54 NaN
13.08 1.47 NaN
12.73 1.00 NaN
12.00 NaN 2.0
33.00 NaN 4.0
23.00 NaN 4.0
12.00 NaN 3.0
我试着用
aggfunc=list
跟着explode
玩,但在这种情况下,顺序丢失了…
感谢这是我的解决方案。您真的不想在x_values
上透视(因为有副本)。因此,在x_values
和id_col
上添加一个新的唯一列(id_col
)和枢轴。然后你需要做一些清理工作:
(d
.assign(id_col=range(len(d)))
.pivot(index=['x_values', 'id_col'], columns='experiment')
.reset_index()
.drop(columns='id_col')
.set_index('x_values')
)
输出如下:
y_values
experiment e f
x_values
12.00 NaN 2.0
12.00 NaN 3.0
12.73 1.00 NaN
13.08 1.47 NaN
13.40 1.54 NaN
23.00 NaN 4.0
33.00 NaN 4.0
一种解决方法是为每个唯一的实验值选择数据,然后将所有这些数据连接起来:
pd.concat([d.loc[d.experiment.eq(c), ['x_values', 'y_values']].rename(columns={'y_values': c}) for c in d.experiment.unique()])
结果:
x_values e f
0 13.40 1.54 NaN
1 13.08 1.47 NaN
2 12.73 1.00 NaN
3 12.00 NaN 2.0
4 33.00 NaN 4.0
5 23.00 NaN 4.0
6 12.00 NaN 3.0
您也可以直接分配新的变量并根据布尔掩码填充它们:
df=pd.DataFrame(
data={
'x_values':[13.4, 13.08, 12.73, 12., 33., 23., 12.],
'y_values': [1.54, 1.47,1.,2.,4.,4.,3.],
'experiment':['e', 'e', 'e', 'f', 'f','f','f']
}
)
df['e'] = df.loc[df['experiment'] == 'e', 'y_values']
df['f'] = df.loc[df['experiment'] == 'f', 'y_values']
df_final = df.drop(columns=['y_values', 'experiment']).set_index(['x_values'])
df_final
-------------------------------------------------
e f
x_values
13.40 1.54 NaN
13.08 1.47 NaN
12.73 1.00 NaN
12.00 NaN 2.0
33.00 NaN 4.0
23.00 NaN 4.0
12.00 NaN 3.0
-------------------------------------------------
如果列experiment
有多个属性,则可以遍历所有惟一值:
for experiment in df['experiment'].unique():
df[experiment] = df.loc[df['experiment'] == experiment, 'y_values']
df_final = df.drop(columns=['y_values', 'experiment']).set_index(['x_values'])
df_final
,产生期望的输出。
这种方法似乎比@Stef提供的方法更有效。然而,随着代码行数的增加,
from time import time
first_approach = []
for i in range(1000):
start = time()
pd.concat([df.loc[df.experiment.eq(c), ['x_values', 'y_values']].rename(columns={'y_values': c}) for c in df.experiment.unique()]).set_index(['x_values'])
first_approach.append(time()-start)
second_approach = []
for i in range(1000):
start = time()
for experiment in df['experiment'].unique():
df[experiment] = df.loc[df['experiment'] == experiment, 'y_values']
df.drop(columns=['y_values', 'experiment']).set_index(['x_values'])
second_approach.append(time()-start)
print(f'Average Time First Approach:t{sum(first_approach)/len(first_approach):.5f}')
print(f'Average Time Second Approach:t{sum(second_approach)/len(second_approach):.5f}')
--------------------------------------------
Average Time First Approach: 0.00403
Average Time Second Approach: 0.00205
--------------------------------------------