我最近一直在使用多级DataFrames,我发现它们可以显着减少大型数据集的计算时间。例如,考虑简单的数据框:
df = pd.DataFrame([
[1, 111, 0], [2, 222, 0], [1, 111, 0],
[2, 222, 1], [1, 111, 1], [2, 222, 2]
], columns=["ID", "A", "B"], index=[1, 1, 2, 2, 3, 3]
)
df.head(6)
ID A B
1 1 111 0
1 2 222 0
2 1 111 0
2 2 222 1
3 1 111 1
3 2 222 2
可以通过ID进行旋转以创建多级数据框:
pivot_df = df.pivot(columns="ID")
pivot_df.head()
A B
ID 1 2 1 2
1 111 222 0 0
2 111 222 0 1
3 111 222 1 2
以这种格式获取数据的好处在于我可以执行" vector"只需引用0级列,即可跨所有ID进行操作:
pivot_df["A"] * (1 + pivot_df["B"])**2
ID 1 2
1 111 222
2 111 888
3 444 999
这些操作对我很有帮助!在现实生活中,我的计算要复杂得多,需要为>执行。 1000个ID。我使用的常见DataFrame大小包含10列(级别0),1000个ID(级别1),350行。
我有兴趣搞清楚做两件事:更新此透视数据框中特定字段的值;为此DataFrame创建一个新列。像
这样的东西pivot_df["A"] = pivot_df["A"] * (1 + pivot_df["B"])**2
或
pivot_df["C"] = pivot_df["A"] * (1 + pivot_df["B"])**2
执行其中任何一项时,我都没有遇到任何错误,但DataFrame保持不变。我也尝试过使用.loc和.iloc,但我没有成功。
我认为问题在于维护计算的DataFrames的多层次结构,但我对使用多级DataFrames并不确定如何有效地解决这个问题感到很陌生。我有一个笨拙的解决方法,效率不高(创建一个计算的DataFrames字典,然后将它们合并在一起......
df_dict = OrderedDict()
df_dict["A"] = pivot_df["A"]
df_dict["B"] = pivot_df["B"]
df_dict["C"] = pivot_df["A"] * (1 + pivot_df["B"])**2
dfs = [val.T.set_index(np.repeat(key, val.shape[1]), append=True).T for key, val in df_dict.iteritems()]
final_df = reduce(lambda x, y: pd.merge(x, y, left_index=True, right_index=True), dfs)
final_df.columns = final_df.columns.swaplevel(0, 1)
或类似地,
df_dict = OrderedDict()
df_dict["A"] = pivot_df["A"] * (1 + pivot_df["B"])**2
df_dict["B"] = pivot_df["B"]
dfs = [val.T.set_index(np.repeat(key, val.shape[1]), append=True).T for key, val in df_dict.iteritems()]
final_df = reduce(lambda x, y: pd.merge(x, y, left_index=True, right_index=True), dfs)
final_df.columns = final_df.columns.swaplevel(0, 1)
这不一定是笨重的(我对解决方法感到自豪),但这肯定不是高效或计算优化的。有没有人有任何建议?
答案 0 :(得分:0)
选项1
不要先转动!
您声明可以方便地进行旋转,因为您可以在新的旋转形式中执行矢量计算。这是一种错误表示,因为您可以在转轴之前轻松执行这些计算。
df['C'] = df["A"] * (1 + df["B"]) ** 2
df.pivot(columns='ID')
A B C
ID 1 2 1 2 1 2
1 111 222 0 0 111 222
2 111 222 0 1 111 888
3 111 222 1 2 444 1998
如果您愿意,可以使用管道式单行程序
df.assign(C=df.A * (1 + df.B) ** 2).pivot(columns='ID')
A B C
ID 1 2 1 2 1 2
1 111 222 0 0 111 222
2 111 222 0 1 111 888
3 111 222 1 2 444 1998
选项2
pd.concat
但要回答你的问题...
pdf = df.pivot(columns='ID')
pd.concat([
pdf.A, pdf.B, pdf.A * (1 + pdf.B) ** 2
], axis=1, keys=['A', 'B', 'C'])
A B C
ID 1 2 1 2 1 2
1 111 222 0 0 111 222
2 111 222 0 1 111 888
3 111 222 1 2 444 1998
选项3
更多pd.concat
在concat之前为列添加另一个级别
pdf = df.pivot(columns='ID')
c = pdf.A * (1 + pdf.B) ** 2
c.columns = [['C'] * len(c.columns), c.columns]
pd.concat([pdf, c], axis=1)
A B C
ID 1 2 1 2 1 2
1 111 222 0 0 111 222
2 111 222 0 1 111 888
3 111 222 1 2 444 1998