我的学生表包含student_id
,course_id
和exam_time
(10k行)。我依靠student_id
和exam_time
来获取会话或一天中的考试数量。我正在构建一个时间表启发式,可以一次更改一次考试时间,因此我需要多次更新此数据透视表。一门课程的考试时间的变化会影响原始数据帧中平均50行。有没有办法更新生成的数据透视表而不重新计算pandas中的整个事物,或者我应该自己跟踪数据透视表上的更改(即通过在更改的插槽中添加和减去1)?
编辑:这是我构建数据透视表的方法。我添加了一列来计算np.sum的数字。我找不到其他功能更快的功能。
sLength = len(df["student_id"])
df["ones"] = pd.Series(np.ones(sLength))
pivot_table = pd.pivot_table(df, rows = "student_id", cols = "exam_time", values = "ones", aggfunc = np.sum)
对于考试时间的变化,我写了这个(假设changed_course
从old_slot
移到new_slot
)
affected_students = df[df["course_id"] == changed_course]["student_id"]
pivot_table[old_slot][affected_students] -= 1
pivot_table[new_slot][affected_students] += 1
答案 0 :(得分:1)
以下是示例代码,其思路是通过减去旧行的数据透视表来更新总数据透视表,并添加新行的数据透视表。
因此,每次更改数据时,您都会调用两次pivot_table()
,一次add()
和一次sub()
:
import numpy as np
import pandas as pd
### create random data
N = 1000
a = np.random.randint(0, 100, N)
b = np.random.randint(0, 30, N)
c = np.random.randint(0, 10, N)
df = pd.DataFrame({"a":a, "b":b, "c":c})
### calculate pivot sum
res = df.pivot_table(values="c", index="a", columns="b", aggfunc="sum", fill_value=0)
### create random rows to change
M = 100
row_index = np.unique(np.random.randint(0, N, M))
old_rows = df.iloc[row_index]
M = old_rows.shape[0]
new_rows = pd.DataFrame({"a":np.random.randint(0, 100, M),
"b":np.random.randint(0, 30, M),
"c":np.random.randint(0, 10, M)})
### update pivot table
sub_df = old_rows.pivot_table(values="c", index="a", columns="b", aggfunc="sum", fill_value=0)
add_df = new_rows.pivot_table(values="c", index="a", columns="b", aggfunc="sum", fill_value=0)
new_res = res.sub(sub_df, fill_value=0).add(add_df, fill_value=0)
### check result
df.iloc[row_index] = new_rows.values
res2 = df.pivot_table(values="c", index="a", columns="b", aggfunc="sum", fill_value=0)
print new_res.astype(int).equals(res2)