我正在尝试用特定子集的上一行(当满足条件时)的值填充新列(上一次)中的每一行。关键是,如果我中断内核并检查值,就可以了。但是,如果运行到最后,则新列中的所有行都将填充为“无”。如果上一行不存在,那么我将用第一个值填充它。
Name First round Previous time
Runner 1 2 2
Runner 2 5 5
Runner 3 5 5
Runner 1 6 2
Runner 2 8 5
Runner 3 4 5
Runner 1 2 6
Runner 2 5 8
Runner 3 5 4
我尝试过的事情:
df.insert(column = "Previous time", value = 999)
def fce(arg):
runner= arg[0]
stat = arg[1]
if stat == 999:
# I used this to avoid filling all rows in a new column again for the same runner
first = df.loc[df['Name'] == runner,"First round"].iloc[0]
df.loc[df['Name'] == runner,"Previous time"] = df.loc[df['Name'] == runner]["First round"].shift(1, fill_value = first)
df["Previous time"] = df[['Name', "Previous time"]].apply(fce, axis=1)
问题是您的函数fce
每行返回None
,因此由术语df[['Name', "Previous time"]].apply(fce, axis=1)
产生的Series是None
的系列。
即,不是使用df.loc
inside函数覆盖数据框,而是需要返回该位置要填充的值。不幸的是,这是不可能的,因为那时您需要知道已经计算出的索引。
一种更好的方法是使用groupby
。这是一种更自然的方法,因为您要对每个组执行操作。如果在apply
之后使用groupby
并返回一个序列,则实际上您为每行定义了一个值。只需记住删除"Name"
添加的额外索引groupby
。
def fce(g):
first = g["First round"].iloc[0]
return g["First round"].shift(1, fill_value=first)
df["Previous time"] == df.groupby("Name").apply(fce).reset_index("Name", drop=True)
非常感谢。请您再回答我一个问题吗?如果我想根据特定的跑步者在比赛前的睡眠时间返回所有回合的平均值,该如何与多列分组方式一起使用。
Expected output:
Name First round Sleep before race Mean
Runner 1 2 8 4
Runner 2 5 7 6
Runner 3 5 8 5
Runner 1 6 8 4
Runner 2 8 7 6
Runner 3 4 9 4,5
Runner 1 2 9 2
Runner 2 5 7 6
Runner 3 5 9 4,5
这对我不起作用。
def last_season(g):
aa = g["First round"].mean()
df["Mean"] = df.groupby(["Name", "Sleep before race"]).apply(g).reset_index(["Name", "Sleep before race"], drop=True)
对每个名称进行gruopby移位,并用原始序列填充缺少的值。
df['Previous time'] = (df.groupby('Name')['First round']
.shift()
.fillna(df['First round'], downcast='infer'))