是否有更有效的方法来将特定值的总 .count() 值带到 Dataframe 中的每一行? (没有合并,最好使用 lambda)
Is there a more efficient way to bring total .count() values of specific value on each row in Dataframe? (without merge, with lambda preferably)
新来的,我的第一个post,请耐心等待:)。
我想在我的 df 中添加一个新列,其中每行 ("Parent_contract")
(重复编号)下的合同编号 ["Child_contract"]
(唯一编号)的总数。
我的以下语句完成了这项工作,但在我当前的 df 上处理它需要相当多的时间。
df["Total_count"] = df.apply(lambda x: df.groupby("Parent_contract")["Child_contract"].count().to_frame().loc[x["Parent_contract"]],axis=1)
非常感谢任何回复。明确一点,我想修改 df 而不是过滤它。
您可以通过更改为:
来加快当前解决方案的速度
fr = df.groupby("Parent_contract")["Child_contract"].count().to_frame()
df["Total_count"] = df.apply(lambda x: fr.loc[x["Parent_contract"]],axis=1)
这提供了超过 3 倍的速度提升。
说明
- 在您当前的解决方案中
df.groupby("Parent_contract")["Child_contract"].count().to_frame() 是
为每一行重新计算。
- 预先计算并分配给 fr 避免
这种重复工作。
性能
测试代码
from random import randint
def generate_data(min_rows):
' Generate dataframe with parent and child columns '
parent_idx, child_idx = 1, 1
d = {'Parent_contract':[],
'Child_contract': []}
while len(d['Parent_contract']) < min_rows:
add = randint(1, 5)
for _ in range(add):
d['Parent_contract'].append(f"p{parent_idx}")
parent_idx += 1
for _ in range(add):
d['Child_contract'].append(f"c{child_idx}")
child_idx += 1
return pd.DataFrame(d)
def posted_method(df):
' Posted method '
df["Total_count"] = df.apply(lambda x: df.groupby("Parent_contract")["Child_contract"].count().to_frame().loc[x["Parent_contract"]],axis=1)
return df
def suggested_method(df):
' Suggested Method '
fr = df.groupby("Parent_contract")["Child_contract"].count().to_frame()
df["Total_count"] = df.apply(lambda x: fr.loc[x["Parent_contract"]],axis=1)
return df
计时(使用timeit)
nRows Posted Method Suggested Method Speed Up
10 18.1 ms 6.37 ms 2.8
1,000 2.05 s 289 ms 7.1
10,000 1 min 5 s 3.01 s 21.5
新来的,我的第一个post,请耐心等待:)。
我想在我的 df 中添加一个新列,其中每行 ("Parent_contract")
(重复编号)下的合同编号 ["Child_contract"]
(唯一编号)的总数。
我的以下语句完成了这项工作,但在我当前的 df 上处理它需要相当多的时间。
df["Total_count"] = df.apply(lambda x: df.groupby("Parent_contract")["Child_contract"].count().to_frame().loc[x["Parent_contract"]],axis=1)
非常感谢任何回复。明确一点,我想修改 df 而不是过滤它。
您可以通过更改为:
来加快当前解决方案的速度fr = df.groupby("Parent_contract")["Child_contract"].count().to_frame()
df["Total_count"] = df.apply(lambda x: fr.loc[x["Parent_contract"]],axis=1)
这提供了超过 3 倍的速度提升。
说明
- 在您当前的解决方案中 df.groupby("Parent_contract")["Child_contract"].count().to_frame() 是 为每一行重新计算。
- 预先计算并分配给 fr 避免 这种重复工作。
性能
测试代码
from random import randint
def generate_data(min_rows):
' Generate dataframe with parent and child columns '
parent_idx, child_idx = 1, 1
d = {'Parent_contract':[],
'Child_contract': []}
while len(d['Parent_contract']) < min_rows:
add = randint(1, 5)
for _ in range(add):
d['Parent_contract'].append(f"p{parent_idx}")
parent_idx += 1
for _ in range(add):
d['Child_contract'].append(f"c{child_idx}")
child_idx += 1
return pd.DataFrame(d)
def posted_method(df):
' Posted method '
df["Total_count"] = df.apply(lambda x: df.groupby("Parent_contract")["Child_contract"].count().to_frame().loc[x["Parent_contract"]],axis=1)
return df
def suggested_method(df):
' Suggested Method '
fr = df.groupby("Parent_contract")["Child_contract"].count().to_frame()
df["Total_count"] = df.apply(lambda x: fr.loc[x["Parent_contract"]],axis=1)
return df
计时(使用timeit)
nRows Posted Method Suggested Method Speed Up
10 18.1 ms 6.37 ms 2.8
1,000 2.05 s 289 ms 7.1
10,000 1 min 5 s 3.01 s 21.5