为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

慕少森 2022-08-11 17:42:54
我在处理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=0years=[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)你能告诉我我到底做错了什么吗?有什么捷径吗?
查看完整描述

3 回答

?
慕雪6442864

TA贡献1812条经验 获得超5个赞

解决方案出奇地短:


df.groupby('inn_main').apply(lambda grp:

    grp[~grp.Help.isin(years).cumsum().shift(fill_value=0).astype(bool)])

结果是:


           inn_main  Help

inn_main                 

Apple    0    Apple    OK

         1    Apple    OK

         2    Apple  2013

Tesla    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  Help

0    Apple    OK

1    Apple    OK

2    Apple  2013

4    Tesla    OK

5    Tesla  2014

7    Tesla    OK

因此,索引 == 7(应删除)的行存在。


查看完整回答
反对 回复 2022-08-11
?
慕的地6264312

TA贡献1817条经验 获得超6个赞

我不完全理解你的要求,但这就是我认为你想要的。给定以下数据帧...


   Help inn_main

0    OK    Apple

1    OK    Apple

2  2013    Apple

3    OK    Apple

4    OK    Tesla

5  2014    Tesla

6    OK    Tesla

...您希望标识 列表中的每一行,并删除其后面的行(在属于给定公司的行中)。如果这是正确的,你可以做得更简单:df.Helpyears


years = range(2012, 2019)

df[~df.groupby('inn_main')['Help'].apply(lambda g: g.isin(years).shift().fillna(False))]

这将提供:


   Help inn_main

0    OK    Apple

1    OK    Apple

2  2013    Apple

4    OK    Tesla

5  2014    Tesla

如果要删除公司内给定行后面的所有行,Valdi_Bo的完整答案将显示如何操作。


查看完整回答
反对 回复 2022-08-11
?
拉风的咖菲猫

TA贡献1995条经验 获得超2个赞

我不太了解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)


查看完整回答
反对 回复 2022-08-11
  • 3 回答
  • 0 关注
  • 123 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号