跳至主要內容
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?

4563博客

全新的繁體中文 WordPress 網站
  • 首頁
  • Python 快速计算增量的方法
未分類
23 6 月 2020

Python 快速计算增量的方法

Python 快速计算增量的方法

資深大佬 : JCZ2MkKb5S8ZX9pq 68

假设表

data = [   ['20:00', 100],   ['20:10', 130],   ['20:20', 190],   ... ] 

期望结果,只统计增量:

data = [   ['20:00', 100],   ['20:10', 30],   ['20:20', 60],   ... ] 

正常写法我会,求一个最 pythonic 的搞法。
印象中好像 map 还是 reduce 啥的能搞这个,但是 py3 好像要导入模块,有点想不起来了。
谁给指点一下。

大佬有話說 (32)

  • 資深大佬 : necomancer

    In [1]: [data[0], list(map(lambda x, y: [x[0],y[1]-x[1]], *zip(data[:-1],data[1:])))]
    Out[1]: [[’20:00′, 100], [[’20:00′, 30], [’20:10′, 60]]]

  • 資深大佬 : watsy0007

    “`python
    fst = lambda x: x[0]
    sec = lambda x: x[1]
    [[fst(item), sec(item) – (0 if idx == 0 else sec(data[idx-1]))] for idx, item in enumerate(data)]
    “`

  • 資深大佬 : necomancer

    sorry

    [data[0]] + list(map(lambda x, y: [x[0],y[1]-x[1]], *zip(data[:-1],data[1:])))

  • 資深大佬 : necomancer

    再 sorry,没看清题……
    In [3]: [data[0]] + list(map(lambda x, y: [y[0],y[1]-x[1]], *zip(data[:-1],data[1:])))
    Out[3]: [[’20:00′, 100], [’20:10′, 30], [’20:20′, 60]]

  • 主 資深大佬 : JCZ2MkKb5S8ZX9pq

    @necomancer 好像是 zip 这步有点问题,py3.7。
    TypeError: <lambda>() takes 2 positional arguments but 55 were given
    还是 map 的调用方法问题?
    我要试试,这两个方法不大用到。

  • 主 資深大佬 : JCZ2MkKb5S8ZX9pq

    顺便给一串测试数据好了,里面是排序后的 tuple。
    [(‘2019-12-09 19:40:03’, 412), (‘2019-12-09 20:10:58’, 4136), (‘2019-12-09 20:41:00’, 6634), (‘2019-12-09 21:11:22’, 9090), (‘2019-12-09 21:41:23’, 11636), (‘2019-12-09 22:11:27’, 14597), (‘2019-12-09 22:41:32’, 17506), (‘2019-12-09 23:11:43’, 20315), (‘2019-12-09 23:41:44’, 22926), (‘2019-12-10 00:11:46’, 24749), (‘2019-12-10 00:41:55’, 26133), (‘2019-12-10 01:11:58’, 27021), (‘2019-12-10 01:42:06’, 27574), (‘2019-12-10 03:08:38’, 28333), (‘2019-12-10 03:38:48’, 28435), (‘2019-12-10 04:08:58’, 28527), (‘2019-12-10 04:39:01’, 28608), (‘2019-12-10 05:09:23’, 28680), (‘2019-12-10 05:39:32’, 28754), (‘2019-12-10 06:09:46’, 28841), (‘2019-12-10 06:39:51’, 29006), (‘2019-12-10 07:09:57’, 29320), (‘2019-12-10 07:40:05’, 29755), (‘2019-12-10 08:10:51’, 30309), (‘2019-12-10 08:40:59’, 30902), (‘2019-12-10 09:11:08’, 31454), (‘2019-12-10 09:41:21’, 31977), (‘2019-12-10 10:11:48’, 32555), (‘2019-12-10 10:42:04’, 33137), (‘2019-12-10 11:12:30’, 33749), (‘2019-12-10 11:42:45’, 34279), (‘2019-12-10 12:12:55’, 34964), (‘2019-12-10 12:43:05’, 35904), (‘2019-12-10 13:13:27’, 36774), (‘2019-12-10 13:43:49’, 37375), (‘2019-12-10 14:13:56’, 37803), (‘2019-12-10 14:44:08’, 38222), (‘2019-12-10 15:14:40’, 38589), (‘2019-12-10 15:44:51’, 38937), (‘2019-12-10 16:15:04’, 39311), (‘2019-12-10 16:45:37’, 39707), (‘2019-12-10 17:15:53’, 40081), (‘2019-12-10 17:45:55’, 40520), (‘2019-12-10 18:16:05’, 40991), (‘2019-12-10 18:46:48’, 41481), (‘2019-12-10 19:17:01’, 41999), (‘2019-12-11 03:23:55’, 47926), (‘2019-12-11 05:24:01’, 48053), (‘2019-12-11 07:24:05’, 48245), (‘2019-12-11 09:24:18’, 48742), (‘2019-12-11 11:24:28’, 49315), (‘2019-12-11 13:24:41’, 50181), (‘2019-12-11 15:24:51’, 50767), (‘2019-12-11 17:24:52’, 51305), (‘2019-12-11 19:24:54’, 52048), (‘2019-12-11 21:25:34’, 52911)]

  • 主 資深大佬 : JCZ2MkKb5S8ZX9pq

    @necomancer 搜了下,看到 pandas 有个 diff 方法。
    [pandas.DataFrame.diff — pandas 0.25.3 documentation]( https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.diff.html)

  • 資深大佬 : necomancer

    是……我脑残了……
    [data[0]] + list(map(lambda x: [x[1][0],x[1][1]-x[0][1]], zip(data[:-1],data[1:])))

  • 資深大佬 : ClericPy

    ![uTools_1576073918431.png]( https://i.loli.net/2019/12/11/aR6rG5JXbQoUql8.png)

    以前写过类似的有序一维数组判断间隔的, 取前几行改改也能用, 主要就是一行

    diffs = [nums[i + 1] – nums[i] for i in range(len(nums) – 1)]

    pythonic 这种东西不是炫技, 牺牲可读性写出来的代码基本等同于蠢

  • 資深大佬 : necomancer

    @ClericPy nums[i]这样会引入一个 O(N) 操作的。

  • 資深大佬 : ipwx

    你这个例子写个 for 难道不是可读性最好的么?

    在这里追求所谓的“Pythonic”未免走火入魔了。

  • 資深大佬 : necomancer

    @JCZ2MkKb5S8ZX9pq pandas 我用得不多。pandas 倒是支持时间作差,但必须是 pandas 的 datetime 类型,字符串直接带入会报错。

  • 主 資深大佬 : JCZ2MkKb5S8ZX9pq

    @necomancer
    df = pd.DataFrame(data, columns=[‘time’, ‘volume’])
    df[‘volume’] = df[‘volume’].diff()
    df[‘volume’].fillna(0, inplace=True)
    df[‘volume’] = df[‘volume’].astype(int)
    print(df)

    diff 可以应用在单独的 series,就是它不打 0 而是用 nan,还要再转一下。

  • 資深大佬 : necomancer

    @JCZ2MkKb5S8ZX9pq 这样啊,谢谢。不过我看求 diff 的时候 pd 好像没有 numpy.diff 里的 prepend 功能,所以无论如何少一个。按你的要求是第一个值不变,原始数据应该在头一个加一个[‘—‘, 0] 进去吧~

  • 資深大佬 : necomancer

    或者直接 df[‘volume’] = numpy.diff(df[‘volume’], prepend=0)

  • 主 資深大佬 : JCZ2MkKb5S8ZX9pq

    @necomancer
    其实感觉这么搞,适用性的确不高。
    如果数据内部想标清楚点,用 dict 来记录每一条,写起来更长,的确嵌套起来不大好读。
    pandas 在这种地方还是挺好的。

    以前都是简单表格直接 prettyTable,感觉 pandas 还是值得深入搞搞。

  • 主 資深大佬 : JCZ2MkKb5S8ZX9pq

    @necomancer 没错,pandas 第一个搞了 0 出来。你不说我还没注意。

  • 主 資深大佬 : JCZ2MkKb5S8ZX9pq

    @necomancer
    这样插行再拿掉感觉也挺蠢的,一整套还是自己写个方法封起来用算了。
    numpy 我不大熟,你感觉 numpy 和 pandas 哪个值得优先地深入看看?

  • 主 資深大佬 : JCZ2MkKb5S8ZX9pq

    @ClericPy 你这个是算间隔的话,长度 1 的时候为什么不是返回 0 ?

  • 資深大佬 : necomancer

    @JCZ2MkKb5S8ZX9pq numpy 是基础。我是做物理的所以很少处理非数字的数据,pandas 除了 read_csv 啥的没咋用过。
    但 pandas 的 dataframe 的底层似乎就是 numpy.ndarray,比如 df.values 会返回 numpy.ndarray ; numpy 的函数也更数学化。但 pandas 的 dataframe 针对各种复杂的数据似更友好一些。

  • 資深大佬 : necomancer

    numpy 去官方文档看看那个入门了解一下各种数组的操作就可以了。你要是处理数据尤其是简单统计一类的比较多的话,多看看 pandas。有些像 dataframe.diff 不那么好用的场景毕竟还可以用 numpy.diff (prepend,append 和 axis ),毕竟数据应该是一样的。

  • 資深大佬 : dongxiao

    1、
    data[0:1] + list(map(lambda obj1, obj2: [obj1[0], obj2[1]-obj1[1]], data[0:-1], data[1:]))

    2、
    from pandas import DataFrame
    frame = DataFrame(data)
    pd.concat([frame.loc[:, 0], frame.loc[:, 1].map(int).diff()], axis=1).combine_first(frame)

  • 主 資深大佬 : JCZ2MkKb5S8ZX9pq

    @necomancer 好的,我去了解一下。

  • 主 資深大佬 : JCZ2MkKb5S8ZX9pq

    @dongxiao 这个是会玩 pandas 的,让我好好消化一下。

  • 資深大佬 : dongxiao

    3、
    import numpy as np
    arr = np.array(data)
    time_arr, num_arr = np.hsplit(arr, [1])
    np.c_[time_arr, np.r_[num_arr[:1], np.diff(num_arr.astype(int), 1, 0)]]

    # 如果要格式转换则
    list(map(lambda obj: [obj[0], int(obj[1])], np.c_[time_arr, np.r_[num_arr[:1], np.diff(num_arr.astype(int), 1, 0)]].tolist()))

  • 資深大佬 : ClericPy

    @JCZ2MkKb5S8ZX9pq #23 呃, 看了这么多回帖才知道你是要数据分析量级比较大的, 那走 pandas 肯定是最好的选择, 性能高一大截还不容易出错

    @necomancer #10 好吧, 我还真没想到复杂度层面, 以前被 CTO 逮住教训了半天别太纠结语法糖, 写过太多屎山, 所以把 pythonic 就直接看作优雅的可读性了

  • 資深大佬 : dangyuluo

    最 pythonic 的写法难道不是用 numpy 么哈哈,shift 第二列然后减一下

  • 資深大佬 : cassidyhere

    from itertools import chain

    l = [100, 130, 190]
    [i – j for i, j in zip(l, chain([0], l[:-1]))]

    这样吧,如果想用 map 还可以用 operator

    import operator

    map(operator.sub, l, chain([0], l[:-1]))

  • 資深大佬 : cassidyhere

    涉及循环或序列里元素间的操作,可以看看 itertools, operator, functools

  • 資深大佬 : wliansheng

    为什么上大部分回答都不能成功运行。除了 @cassidyhere 可以得到 [100, 30, 60]

  • 主 資深大佬 : JCZ2MkKb5S8ZX9pq

    @cassidyhere
    你这一写,我感觉以前看 cookbook 的时候都见过,太久不用都还回去了。/捂脸

    不过这个题目我后来想想,还是有一些细节可以探讨。几种方法效率上还是有点区别。

  • 資深大佬 : cfwyy

    不知道啥叫 pythonic,见笑了。

    newdata=data[0:1]
    newdata.extend([[data[i][0],data[i][1]-data[i-1][1]] for i in range(1,len(data))])

文章導覽

上一篇文章
下一篇文章

AD

其他操作

  • 登入
  • 訂閱網站內容的資訊提供
  • 訂閱留言的資訊提供
  • WordPress.org 台灣繁體中文

51la

4563博客

全新的繁體中文 WordPress 網站
返回頂端
本站採用 WordPress 建置 | 佈景主題採用 GretaThemes 所設計的 Memory
4563博客
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?
在這裡新增小工具