写了 2 天的 Python ,有点奇怪的感觉。。。

2024-03-28 20:00:55 +08:00
 woodytang

听说 pandas 很好用,于是决定试一下

目的是这样的: user, amount, datetime A 10 2021-02-12 10:00:00 A 20 2021-03-12 10:00:00 B 30 2021-05-12 10:00:00 B 10 2021-06-12 10:00:00 C 5 2021-05-12 10:00:00 C 10 2021-06-12 10:00:00 C 20 2021-06-12 10:00:00 这是我们常见的数据库的表

最后要做成这样的效果 2021-02 2021-03 2021-05 2021-06 A 10 20 0 0 B 0 0 30 10 C 0 0 5 30


首先我想问一下,这样的需求,大家首先会想到用什么方案(语言,框架,库)做?

column_names = [desc[0] for desc in cursor.description] df = pd.DataFrame(rows, columns=column_names) df['datetime'] = pd.to_datetime(df['datetime']) df['归属年月'] =(df['datetime'].dt.year.astype(str)+ df['datetime'].dt.strftime('%m').astype(str)).astype(int)

到这里把时间字段理好了,变成数字,让它可以排序

grouped_data = df.groupby(['user', '归属年月'])['amount'].sum().reset_index() grouped_data = grouped_data.sort_values('归属年月') 来个二维分组,然后按照‘2021-05’这个来排序一下

df_pivot = pd.pivot_table(grouped_data, index=['user'], columns='归属年月', values='amount', aggfunc='sum').reset_index().fillna(0)

到这里就好了

代码十分简洁,但是这种代码真的有可读性吗?好维护吗?

如果我要算 A 用户所有金额汇总,可以这样写: df_pivot['余额'] = df_pivot.iloc[:, 1:].sum(axis=1)

这个= 让我震惊了,明明执行了函数操作,看上去像是一个赋值操作,这个 python 是怎么实现的?

我编辑器用的 vsc ,python 没有 type hint ,这个有解吗,难道一边写要一边查文档?

还有元组的简写法

a= 1,2,3

看到这个我也是懵了

有没有 pythoner 解答一下,这个语言真的适合写正经项目吗?


js 有 ts 就变得完美了,我很喜欢 python 的生态,有什么可以愉快写 python 的办法?

5031 次点击
所在节点    程序员
33 条回复
dekuofa
2024-03-29 06:47:50 +08:00
建议直接上 polars
bianhui
2024-03-29 08:22:14 +08:00
静态语言后遗症。多写就好了。世界上流行的语言都有他自己的优势,你要抛开你固有观念,去接纳新鲜事物
nno
2024-03-29 08:46:29 +08:00
"这个= 让我震惊了,明明执行了函数操作,看上去像是一个赋值操作,这个 python 是怎么实现的?"
这里其实是 pandas 的 DataFrame 重写了__setitem__接口,当你将对象当做一个 map 来操作的时候,就会触发__getitem__、__setitem__这些内置接口
darkengine
2024-03-29 08:47:13 +08:00
光考虑要实现什么功能还不够,还需要考虑:

1 ,这个功能需要长期维护迭代,还是就一次性的数据处理
2 ,团队/个人的能力:包括能不能快速上手某个语言,熟悉某些库,使用某语音,某些库后续好不好招人
suuuch
2024-03-29 09:19:40 +08:00
Python 在我的理解里面,是完全为了非科班的人员进入编程的最便捷的路径。

贴近自然语言的语法,脚本直接执行。在学习和自己想快速实现某些小功能的情况下,将环境准备成本将到最低。

比如说,openai 接口刚出来那会,我跟两个朋友弄了个账号一起用。我为了方便,在我买的美帝服务器上做一个转发,及我从国内把 请求服务器上的接口,再从服务器上转发到 openai 的 api 上。。写一下 flask 的固定 token 鉴权,用 supervisor 监控一下。不考虑任何性能。半个小时搞完。。。
SmiteChow
2024-03-29 10:38:48 +08:00
还需要多用用,少提见解。
yjhatfdu2
2024-03-29 11:12:26 +08:00
这不是一句 sql 查询就能解决的事情吗,为啥要变复杂?
xgdgsc
2024-03-29 12:35:39 +08:00
不喜欢这种可以用 julia 无脑 for 循环处理数据
song135711
2024-03-29 13:25:55 +08:00
ide 试试 pycharm 社区版。
计算机语言是工具,重要的是使用工具的人。
mkroen
2024-03-29 14:04:07 +08:00
@xingfa 感谢分享,已经在做眼保健操了
woodytang
2024-03-29 16:55:14 +08:00
@zhzy 大哥,感谢你啊,把我的问题写出来了
woodytang
2024-03-29 17:01:46 +08:00
@yjhatfdu2 请赐教,sql 怎么一句写出来~~
yjhatfdu2
2024-04-02 11:23:59 +08:00
@woodytang pg 下,如果可以用程序生成返回列然后拼接 SQL ,那么很简单
//创建测试表
create table test3("user" text,amount int,datetime timestamp);
insert into public.test3 (user, amount, datetime)
values ('A', 10, '2021-02-12 10:00:00.000000'),
('A', 20, '2021-03-12 10:00:00.000000'),
('B', 30, '2021-05-12 10:00:00.000000'),
('B', 10, '2021-06-12 10:00:00.000000'),
('C', 10, '2021-06-12 10:00:00.000000'),
('C', 20, '2021-06-12 10:00:00.000000'),
('C', 5, '2021-05-12 10:00:00.000000');
//使用 crosstab 进行 pivot
select *
from crosstab($$select "user",date_trunc('month',datetime)::date::text,sum(amount)
from test3 group by 1,2 order by 1,2 $$,
'select distinct date_trunc(''month'',datetime)::date::text from test3 order by 1') as ct(
"user" text,
"2021-02" text,
"2021-03" text,
"2021-05" text,
"2021-06" text
);
//结果
user | 2021-02 | 2021-03 | 2021-05 | 2021-06
------+---------+---------+---------+---------
A | 10 | 20 | |
B | | | 30 | 10
C | | | 5 | 30

如果要动态生成返回列名,那么确实是相当的麻烦,因为 pg 的查询必须显式制定列,只能用非常别扭的方式
-- 创建一个函数,实际查询的 SQL ,可以反复使用
create or replace function crosstabquery(_t anyelement) returns setof anyelement as
$$
declare
column_list text;
begin
select string_agg(format('%I text', d), ',')
into column_list
from (select distinct date_trunc('month', datetime)::date::text d from test3 order by 1) r;
return query execute ($b$select *
from crosstab($a$select "user",date_trunc('month',datetime)::date::text,sum(amount)
from test3 group by 1,2 order by 1,2 $a$,
'select distinct date_trunc(''month'',datetime)::date::text from test3 order by 1') as ct("user" text,$b$ ||
column_list||')' );
end ;
$$
language plpgsql;
-- 创建返回类型,每次使用前调用
do
$$
declare
column_list text;
begin
select string_agg(format('%I text', d), ',')
into column_list
from (select distinct date_trunc('month', datetime)::date::text d from test3 order by 1) r;
drop type if exists __t;
execute format('create type __t as ("user" text, %s)', column_list);
end
$$ language plpgsql;
-- 返回实际结果
select * from crosstabquery(null::__t);
user | 2021-02-01 | 2021-03-01 | 2021-05-01 | 2021-06-01
------+------------+------------+------------+------------
A | 10 | 20 | |
B | | | 30 | 10
C | | | 5 | 30
(3 rows)

不过如果可以动态生成 sql ,就别用下面这个方案,实在是别扭

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1027882

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX