如何通过groupby对象中的所有行计算来改善功能?

如何解决如何通过groupby对象中的所有行计算来改善功能?

说我有这个简单的数据框-

dic = {'firstname':['Steve','Steve','Steve'],'lastname':['Johnson','Johnson','Johnson'],'company':['CHP','CHP','CHP'],'faveday':['2020-07-13','2020-07-20','2020-07-16','2020-10-14','2020-10-28','2020-10-21'],'paid':[200,300,550,100,900,650]}
df = pd.DataFrame(dic)
df['faveday'] = pd.to_datetime(df['faveday'])
print(df)

有输出-

  firstname lastname company    faveday  paid
0     Steve  Johnson     CHP 2020-07-13   200
1     Steve  Johnson     CHP 2020-07-20   300
2     Steve  Johnson     CHP 2020-07-16   550
3     Steve  Johnson     CHP 2020-10-14   100
4     Steve  Johnson     CHP 2020-10-28   900
5     Steve  Johnson     CHP 2020-10-21   650

我希望能够将最近的行保持在另一行的7天内,但其付费列的总和必须大于1000。

如果我想应用7天功能,则可以使用-

def sefd (x): 
    return np.sum((np.abs(x.values-x.values[:,None])/np.timedelta64(1,'D'))<=7,axis=1)>=2
s=df.groupby(['firstname','lastname','company'])['faveday'].transform(sefd)
df['seven_days']=s
df = df[s]
del df['seven_days']

这将保留所有条目(所有这些条目均在另一个根据名,姓和公司分组的节日前7天内)。

如果我想应用一个函数来为同一个人和同一家公司保留行,并且总支付金额> 1000,我会使用-

df = df[df.groupby(['lastname','firstname','company'])['paid'].transform(sum) > 1000]

只是一个简单的transform(sum)函数

这还将保留所有条目(因为所有条目都使用相同的名称和公司,并且总和大于1000)。

但是,如果我们要同时合并这两个功能,则实际上不会包含一行。

我想要的输出是-

  firstname lastname company    faveday  paid
0     Steve  Johnson     CHP 2020-07-13   200
1     Steve  Johnson     CHP 2020-07-20   300
2     Steve  Johnson     CHP 2020-07-16   550
4     Steve  Johnson     CHP 2020-10-28   900
5     Steve  Johnson     CHP 2020-10-21   650

请注意,索引3不再有效,因为它仅在索引5的7天内,但是如果您要对已支付的索引3和已支付的索引5进行求和,则该数字仅为750(

还必须注意,由于索引0、1和2都在7天内,因此算作一个汇总组(200 + 300 + 550> 1000)。

逻辑是,我想首先查看(基于一组姓氏,姓氏和公司名称)是否一个节日在另一个节日的7天内。然后,在确认这一点之后,查看这几天的付费栏的总和是否超过1000。如果是,请将这些索引保留在数据框中。否则,请不要。

给我的建议答案是-

df=df.sort_values(["firstname","lastname","company","faveday"])

def date_difference_from(x,df):
    return abs((df.faveday - x).dt.days)

def grouped_dates(grouped_df):
    keep = []
    for idx,row in grouped_df.iterrows():
        within_7 = date_difference_from(row.faveday,grouped_df) <= 7
        keep.append(within_7.sum() > 1 and grouped_df[within_7].paid.sum() > 1000)
    msk = np.array(keep)
    
    return grouped_df[msk]

df = df.groupby(["firstname","company"]).apply(grouped_dates).reset_index(drop=True)
print(df)

这对于像这样的小型数据集非常适用,但是当我将其应用于更大的数据集(10,000行以上)时,会出现一些不一致之处。

有什么办法可以改善这段代码?

解决方法

我找到了一种解决方案,该解决方案避免在7天之内循环idx比较其他行,但是涉及unstackreindex,因此会增加内存使用率(我尝试使用{{1} }滚动方法,但事实证明,该方法超出了我的专业知识。适合您所要求的规模。尽管此解决方案与您提供的玩具df相当,但在较大的数据集上要快几个数量级。

编辑:一次允许多次存款。

获取此数据(默认为_get_window_bounds,默认为random.choice)

replace=True

和代码

import string
np.random.seed(123)
n = 40
df = pd.DataFrame([[a,b,faveday,paid]
    for a in string.ascii_lowercase
    for b in string.ascii_lowercase
    for faveday,paid in zip(
        np.random.choice(pd.date_range('2020-01-01','2020-12-31'),n),np.random.randint(100,1200,n))
    ],columns=['firstname','lastname','company','faveday','paid'])
df['faveday'] = pd.to_datetime(df['faveday'])
df = df.sort_values(["firstname","lastname","company","faveday"]).reset_index(drop=True)

>>>print(df)
      firstname lastname company    faveday  paid
0             a        a       a 2020-01-03  1180
1             a        a       a 2020-01-18   206
2             a        a       a 2020-02-02   490
3             a        a       a 2020-02-09   615
4             a        a       a 2020-02-17   471
...         ...      ...     ...        ...   ...
27035         z        z       z 2020-11-22   173
27036         z        z       z 2020-12-22   863
27037         z        z       z 2020-12-23   675
27038         z        z       z 2020-12-26  1165
27039         z        z       z 2020-12-30   683

[27040 rows x 5 columns]

仍然以1.5秒(相对于当前代码的143秒)运行并返回

def get_valid(df,window_size=7,paid_gt=1000,groupbycols=['firstname','company']):
    # df_clean = df.set_index(['faveday'] + groupbycols).unstack(groupbycols)
        # # unstack names to bypass groupby
    df_clean = df.groupby(['faveday'] + groupbycols).paid.agg(['size',sum])
    df_clean.columns = ['ct','paid']
    df_clean = df_clean.unstack(groupbycols)
    df_clean = df_clean.reindex(pd.date_range(df_clean.index.min(),df_clean.index.max())).sort_index() # include all dates,to treat index as integer
    window = df_clean.fillna(0).rolling(window_size + 1).sum()
        # notice fillna to prevent false NaNs while summing
    df_clean = df_clean.paid * ( # multiply times a mask for both conditions
        (window.ct > 1) & (window.paid > paid_gt)
        ).replace(False,np.nan).bfill(limit=7)
        # replacing with np.nan so we can backfill to include all dates in window
    df_clean = df_clean.rename_axis('faveday').stack(groupbycols)\
        .reset_index(level='faveday').sort_index().reset_index()
        # reshaping to original format
    return df_clean

df1 = get_valid(df,'company'])

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-