【问题标题】:Count cumulative and sequential values of the same sign in Pandas series计算 Pandas 系列中相同符号的累积值和顺序值
【发布时间】:2018-03-22 09:48:10
【问题描述】:

我编写了这段代码,用于计算数据框列中符号更改(从正数变为负数,反之亦然)以来的时间。

df = pd.DataFrame({'x': [1, -4, 5, 1, -2, -4, 1, 3, 2, -4, -5, -5, -6, -1]})

for column in df.columns:
    days_since_sign_change = [0]
    for k in range(1, len(df[column])):
        last_different_sign_index = np.where(np.sign(df[column][:k]) != np.sign(df[column][k]))[0][-1]
        days_since_sign_change.append(abs(last_different_sign_index- k))
    df[column+ '_days_since_sign_change'] = days_since_sign_change        
    df[column+ '_days_since_sign_change'][df[column] < 0] = df[column+ '_days_since_sign_change'] *-1 
# this final stage allows the "days_since_sign_change" column to also indicate if the sign changed 
# from - to positive or from positive to negative.

In [302]:df
Out[302]: 
    x  x_days_since_sign_change
0   1                         0
1  -4                        -1
2   5                         1
3   1                         2
4  -2                        -1
5  -4                        -2
6   1                         1
7   3                         2
8   2                         3
9  -4                        -1
10 -5                        -2
11 -5                        -3
12 -6                        -4
13 -1                        -5

问题:对于大型数据集(150,000 * 50,000),python 代码非常慢。如何加快速度?

【问题讨论】:

  • 你能举一个大型数据集给性能带来麻烦的例子吗?
  • 大数据集类似于给定的样本数据,但有数百或百万行。他的问题是如何重新编写代码以更快地运行。

标签: python pandas numpy dataframe


【解决方案1】:

您可以使用cumcount

s=df.groupby(df.x.gt(0).astype(int).diff().ne(0).cumsum()).cumcount().add(1)*df.x.gt(0).replace({True:1,False:-1})
s.iloc[0]=0
s
Out[645]: 
0     0
1    -1
2     1
3     2
4    -1
5    -2
6     1
7     2
8     3
9    -1
10   -2
11   -3
12   -4
13   -5
dtype: int64

【讨论】:

    【解决方案2】:

    您当然可以在没有循环的情况下执行此操作。如果 x 中的值小于 0,则使用 -1 创建符号列,否则创建 1。然后根据当前行与前一行的值的差异对该符号列进行分组,并获得累积总和。

    df['x_days_since_sign_change'] = (df['x'] > 0).astype(int).replace(0, -1)
    
    df.iloc[0,1] = 0
    df.groupby((df['x_days_since_sign_change'] != df['x_days_since_sign_change'].shift()).cumsum()).cumsum()
    
    
        x   x_days_since_sign_change
    0   1   0
    1   -4  -1
    2   5   1
    3   6   2
    4   -2  -1
    5   -6  -2
    6   1   1
    7   4   2
    8   6   3
    9   -4  -1
    10  -9  -2
    11  -14 -3
    12  -20 -4
    13  -21 -5
    

    【讨论】:

    • 我正在使用 cumcount ~ :-) 顺便说一句很好的答案
    • 我都+1,但我选择了这个答案,因为它是第一个。
    猜你喜欢
    • 1970-01-01
    • 2019-06-06
    • 2020-07-18
    • 1970-01-01
    • 2014-01-14
    • 1970-01-01
    • 2018-12-04
    • 2021-04-25
    • 1970-01-01
    相关资源
    最近更新 更多