这似乎是一个非常基本的问题,之前曾有人问过,但我找不到答案。
我有一个数据框。我想做一个groupby,然后应用一个函数。我希望函数修改原始数据框中的列。这些选项都不起作用:
import pandas as pd
df = pd.DataFrame(list(zip(list('abababa'), [1,2,3,4,1,2,3], [5,4,3,2,1,2,3])),
columns=["ab", "x", "y"])
print(df,"\n")
### Attempt #1
def change_y(tab):
tab.y = tab.y.min()
df.groupby(df.ab).apply(change_y)
### Attempt #2
def change_y(tab):
tab.loc[:,"y"] = tab.y.min()
df.groupby(df.ab).apply(change_y)
### Attempt #3
def change_y(tab):
tab.at[:,"y"] = tab.y.min()
df.groupby(df.ab).apply(change_y)
### Attempt #4
def change_y(tab):
tab.loc[tab.index,"y"] = tab.y.min()
df.groupby(df.ab).apply(change_y)
但是,这可行:
### Attempt #5 -- This one works
def change_y(big_tab,tab):
big_tab.loc[tab.index,"y"] = tab.y.min()
df.groupby(df.ab).apply(lambda tab: change_y(df,tab))
print(df,"\n")
因此,我了解了#5为何起作用,但我不明白为什么1-4都不起作用。我误会了groupby吗?我认为它没有复制基础数据框,而只是在基础数据框上构造索引并将它们传递给函数。在这种情况下,似乎1-4中的至少一个应该可以工作!
groupby实际上是否为每个组制作数据帧的副本?看来这是不必要且低效的。
如果确实进行复制,则除了#5之外,还有其他解决方案吗?我确实知道我可以简单地让函数创建一个新的Series并在最后分配它:
df.y = df.groupby(df.ab).apply(lambda tab: tab.x = tab.y)
但是由于其他原因,在这种情况下,我不想这样做。
答案 0 :(得分:0)
看来,groupby实际上确实在制作副本。我想避免这种情况,因为我有一个非常庞大的数据框。我确实提出了这个解决方案,就像我的数据框很大一样丑陋。我只需要复制数据框的一列。 (它可以是任何列;我只对索引感兴趣。)
感谢所有提供帮助的人。
import pandas as pd
df = pd.DataFrame(list(zip(list('abababa'), [1,2,3,4,1,2,3], [5,4,3,2,1,2,3])),
columns=["ab", "x", "y"])
print(df,"\n")
def change_y(big_tab,ab_tab):
indx = ab_tab.index
tab = big_tab.loc[indx] # I can do all but the update with tab.
big_tab.loc[indx,"y"] = tab.y.min()
df.ab.groupby(df.ab).apply(lambda ab_tab: change_y(df,ab_tab))
print(df,"\n")