简化代码。我的作品,但看起来像地狱一样丑陋

我在处理Python时遇到了麻烦。我有PD数据帧,我需要删除所有行,这些行是在特定值之后(在代码值中写入称为年份的列表)所有值都应按公司名称分组,因为这些obserevation属于“inn_main”列中提到的公司。我真的不明白如何使用Pandas功能做到这一点。我找到了一种方法,但它非常丑陋,效率不高。


import pandas as pd 

data = {'inn_main':['Apple', 'Apple', 'Apple', 'Apple', 'Tesla', 'Tesla', 'Tesla'], 'Help':['OK', 'OK', 2013, 'OK','OK', 2014, 'OK']} 

df = pd.DataFrame(data) 

droper=[]

block=0

years=[2012,2013,2014,2015,2016,2017,2018]

for j in range(len(list(df['Help'].groupby(df['inn_main'])))):

    alarm=0

    for i in range(len(list(df['Help'].groupby(df['inn_main']))[j][1].index.values)):

        if list(df['Help'].groupby(df['inn_main']))[j][1][list(df['Help'].groupby(df['inn_main']))[j][1].index.values[i].astype(int)] in years:

            block=1

            alarm=1

        if block==1:

            block=0

        else:

            if alarm==1:

                droper.append(list(df['Help'].groupby(df['inn_main']))[j][1].index.values[i].astype(int))   

df.drop(index=droper)

你能告诉我我到底做错了什么吗?有什么捷径吗?


慕少森
浏览 124回答 3
3回答

慕雪6442864

解决方案出奇地短:df.groupby('inn_main').apply(lambda grp:    grp[~grp.Help.isin(years).cumsum().shift(fill_value=0).astype(bool)])结果是:           inn_main  Helpinn_main                 Apple    0    Apple    OK         1    Apple    OK         2    Apple  2013Tesla    4    Tesla    OK         5    Tesla  2014详:df.groupby('inn_main')- 按公司对数据帧进行分组。apply(lambda grp:- 将 lambda 函数应用于每个组。grp.Help.isin(years)- 帮助是否以年为单位有价值?.cumsum()- 上述问题的累计总和。shift(fill_value=0)- 将结果向下移动1行,用0填充任何NaN(实际上是第一项)。astype(bool)- 将整数转换为布尔。~- 否定上述结果[...]- 在布尔索引中使用上述结果。grp[...]- 从当前组返回“好”行(它们将是当前组的结果的一部分)。注意:ASGM 的解决方案仅删除第一行,在包含“帮助”的任何行之后,第一行“确定”。要确认这一点,请将另一行包含 Tesla 和 OK 添加到 DataFrame 并运行他的代码。结果是:  inn_main  Help0    Apple    OK1    Apple    OK2    Apple  20134    Tesla    OK5    Tesla  20147    Tesla    OK因此,索引 == 7(应删除)的行存在。

慕的地6264312

我不完全理解你的要求,但这就是我认为你想要的。给定以下数据帧...   Help inn_main0    OK    Apple1    OK    Apple2  2013    Apple3    OK    Apple4    OK    Tesla5  2014    Tesla6    OK    Tesla...您希望标识 列表中的每一行,并删除其后面的行(在属于给定公司的行中)。如果这是正确的,你可以做得更简单:df.Helpyearsyears = range(2012, 2019)df[~df.groupby('inn_main')['Help'].apply(lambda g: g.isin(years).shift().fillna(False))]这将提供:   Help inn_main0    OK    Apple1    OK    Apple2  2013    Apple4    OK    Tesla5  2014    Tesla如果要删除公司内给定行后面的所有行,Valdi_Bo的完整答案将显示如何操作。

拉风的咖菲猫

我不太了解panda,也不知道你想做什么,但这里是重构的代码,用于迭代列表而不是使用索引:import pandas as pd data = {'inn_main':['Apple', 'Apple', 'Apple', 'Apple', 'Tesla', 'Tesla', 'Tesla'], 'Help':['OK', 'OK', 2013, 'OK','OK', 2014, 'OK']} df = pd.DataFrame(data) droper=[]years=[2012,2013,2014,2015,2016,2017,2018]for j in list(df['Help'].groupby(df['inn_main'])):    alarm=False    for i in j[1].index.values:        if j[1][i.astype(int)] in years:            alarm=True        elif alarm:            droper.append(i.astype(int))   df.drop(index=droper)
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python