【发布时间】:2019-07-23 20:20:22
【问题描述】:
我正在尝试旋转 pandas 数据框,但数据遵循一种我似乎无法旋转的奇怪格式。数据结构如下:
Date, Location, Action1, Quantity1, Action2, Quantity2, ... ActionN, QuantityN
<date> 1 Lights 10 CFloor 1 ... Null Null
<date2> 2 CFloor 2 CWalls 4 ... CBasement 15
<date3> 2 CWalls 7 CBasement 4 ... NUll Null
从本质上讲,每个动作都将始终附加一个数量(可能为 0),但 null 动作永远不会有数量(数量将为空)。我试图实现的格式如下:
Lights CFloor CBasement CWalls
1 10 1 0 0
2 0 2 19 11
行的索引成为位置,而列成为跨多个活动列找到的任何唯一操作。将数据拉到一起时,每行/列的值是与动作关联的每个数量的总和(即 Action1 对应于 Quantity1)。有没有办法使用原生 pandas 枢轴功能来做到这一点?
我当前的代码对所有活动列执行 ravel 以获取所有唯一活动的列表。它还将从 Location 列中获取所有唯一位置。拥有唯一列后,我会创建一个空数据框并用零填充:
Lights CFloor CBasement CWalls
1 0 0 0 0
2 0 0 0 0
然后我使用 itertuples() 方法迭代旧数据帧(我被告知它比 iterrows() 快得多)并填充新数据帧。这个空的数据框充当模板,存储在内存中并稍后填充。
#Creates a template from the dataframe
def create_template(df):
act_cols = ['Activity01', 'Activity02', 'Activity03', 'Activity04']
activities = df[act_cols]
flat_acts = activities.values.ravel('K')
unique_locations = pd.unique(df['Location'])
unique_acts = pd.unique(flat_acts)
pivot_template = pd.DataFrame(index=unique_locations, columns=unique_acts).fillna(0)
return pivot_template
#Fills the template from the dataframe
def create_pivot(df, pivot_frmt):
act_cols = ['Activity01', 'Activity02', 'Activity03', 'Activity04']
quant_cols = ['Quantity01', 'Quantity02', 'Quantity03', 'Quantity04']
for row in df.itertuples():
for act, quantity in zip(act_cols, quant_cols):
act_val = getattr(row, act)
if pd.notna(act_val):
quantity_val = getattr(row, quantity)
location = getattr(row, 'Location')
pivot_frmt.loc[location, act_val] += quantity_val
return pivot_frmt
虽然我的解决方案有效,但在处理大型数据集时速度非常慢,并且需要 10 秒或更长时间才能完成此类操作。任何帮助将不胜感激!
【问题讨论】:
-
更新:经过一番研究,我发现交叉表函数在传递值时似乎具有与枢轴相同的功能。我的初始测试表明它按我的预期工作,但一次只能处理一列和一个值集。这是我的测试代码: pd.crosstab(index=df['Location'], columns=df['Activity01'], values=df['Quantity01'], aggfunc=np.sum).fillna(0)跨度>