【问题标题】:Python help optimize this functionPython帮助优化这个功能
【发布时间】:2021-01-24 16:52:59
【问题描述】:
data = 
        Symbol   Value  Day
0         AACG  1.8708    1
1         AACG  1.8500    2
2         AACG  1.8869    3
3         AACG  1.8200    4
4         AACG  1.8578    5
...        ...     ...  ...
3407024   ZYXI   5.25    1
3407025   ZYXI   4.96    2
3407026   ZYXI   4.99    3
3407027   ZYXI   4.99    4
3407028   ZYXI   4.95    5
...        ...    ...  ...
3407250   ZYXI  8.1500  227
3407251   ZYXI  8.2600  228
3407252   ZYXI  8.3900  229
3407253   ZYXI  8.1200  230
3407254   ZYXI  8.0700  231
import pandas as pd
import numpy as np

for index, row in data.iterrows():
    for i in range(1, 91):
        cstr = 'day-' + str(i)
        val = 'NaN'
        try:
            val = float(data[np.logical_and(data['Symbol'] == row['Symbol'],
                            data['Day'] == row['Day'] - i)].Value)
        except:
            val = 'NaN'
        data.loc[index,cstr] = val

函数循环遍历数据框中的每一行

对于数据框中的每一行,它循环 90 次 (i)

对于每个循环,它会添加一个带有值的列

值是数据框中的值,符号与行相同,但天为从行减去i的天

output =
  Symbol   Value  Day   day-1   day-2   day-3   day-4... day-89 day-90
0   AACG  1.8708    1     NaN     NaN     NaN     NaN
1   AACG  1.8500    2  1.8708     NaN     NaN     NaN
2   AACG  1.8869    3  1.8500  1.8708     NaN     NaN
3   AACG  1.8200    4  1.8869  1.8500  1.8708     NaN
4   AACG  1.8578    5  1.8200  1.8869  1.8500  1.8708
5   AACG  1.8709    6  1.8578  1.8200  1.8869  1.8500
6   AACG  1.8700    7  1.8709  1.8578  1.8200  1.8869
7   AACG  1.8800    8  1.8700  1.8709  1.8578  1.8200
8   AACG  1.8000    9  1.8800  1.8700  1.8709  1.8578
9   AACG  1.7900   10  1.8000  1.8800  1.8700  1.8709

【问题讨论】:

  • 请从intro tour 重复on topic 和how to ask。您似乎正在为您尚未描述的问题寻找代码审查 - 其中任何一个都表明 Stack Overflow 不适合您的问题。
  • 您的预期输出是什么?你想做什么。你能用简单的英语解释一下吗
  • @JoeFerndz 我基本上是将前 90 天的值作为列添加到每一行,所以每一行都是一组前 90 天的值,可以绘制图表
  • 您想要 90 列? 90 列中的每一列的值是多少?你能拿 2 行给我们示例输出吗
  • @JoeFerndz 我添加了它

标签: python pandas numpy optimization


【解决方案1】:

您可以执行以下操作:

  • 第 1 步:创建一个包含 90 列的字典并将 np.nan 分配给它。 每列将有 Day_ + str(i) 其中 i 的范围从 1 到 90。
  • 第 2 步:创建一个包含这 90 列的数据框。
  • 第 3 步:将数据帧连接到原始数据帧。轮到你了 有 90 列以 np.NaN 作为值。
  • 第 4 步:现在在 groupby(Symbol) 之后执行 Value 的 shift(1)
  • 第 5 步:现在从 2 到 90 迭代并执行 Day_1 的 shift(1)。那 将为您提供所有必需的值。

执行此操作的代码是:

c = ['Symbol','Value','Day']
d = [['AACG',1.8708,1],
     ['AACG',1.8500,2],
     ['AACG',1.8869,3],
     ['AACG',1.8200,4],
     ['AACG',1.8578,5],
     ['ZYXI',5.25,1],
     ['ZYXI',4.96,2],
     ['ZYXI',4.99,3],
     ['ZYXI',4.99,4],
     ['ZYXI',4.95,5]]

import pandas as pd
import numpy as np
df = pd.DataFrame(d,columns=c)
cols = {'Day_'+str(i):np.NaN for i in range(1,91)}

df = pd.concat([df,pd.DataFrame(cols,index=df.index)], axis=1)

for i in range (1,91):
    df['Day_'+str(i)] = df.groupby(['Symbol'])['Value'].transform(lambda x:x.shift(i))

print (df)

这个输出将是:

  Symbol   Value  Day   Day_1   Day_2  ...  Day_86  Day_87  Day_88  Day_89  Day_90
0   AACG  1.8708    1     NaN     NaN  ...     NaN     NaN     NaN     NaN     NaN
1   AACG  1.8500    2  1.8708     NaN  ...     NaN     NaN     NaN     NaN     NaN
2   AACG  1.8869    3  1.8500  1.8708  ...     NaN     NaN     NaN     NaN     NaN
3   AACG  1.8200    4  1.8869  1.8500  ...     NaN     NaN     NaN     NaN     NaN
4   AACG  1.8578    5  1.8200  1.8869  ...     NaN     NaN     NaN     NaN     NaN
5   ZYXI  5.2500    1     NaN     NaN  ...     NaN     NaN     NaN     NaN     NaN
6   ZYXI  4.9600    2  5.2500     NaN  ...     NaN     NaN     NaN     NaN     NaN
7   ZYXI  4.9900    3  4.9600  5.2500  ...     NaN     NaN     NaN     NaN     NaN
8   ZYXI  4.9900    4  4.9900  4.9600  ...     NaN     NaN     NaN     NaN     NaN
9   ZYXI  4.9500    5  4.9900  4.9900  ...     NaN     NaN     NaN     NaN     NaN

我将为AACG 创建一个包含 90 多行的数据框,并向您展示结果,以便您看到 Day_90 将具有正确的值。

我又添加了几条记录,以显示 90 天列已填满。

>>> df.iloc[80:100]
   Symbol   Value  Day   Day_1   Day_2  ...  Day_86  Day_87  Day_88  Day_89  Day_90
80   AACG  1.8659   81  1.8658  1.8657  ...     NaN     NaN     NaN     NaN     NaN
81   AACG  1.8660   82  1.8659  1.8658  ...     NaN     NaN     NaN     NaN     NaN
82   AACG  1.8661   83  1.8660  1.8659  ...     NaN     NaN     NaN     NaN     NaN
83   AACG  1.8662   84  1.8661  1.8660  ...     NaN     NaN     NaN     NaN     NaN
84   AACG  1.8663   85  1.8662  1.8661  ...     NaN     NaN     NaN     NaN     NaN
85   AACG  1.8664   86  1.8663  1.8662  ...     NaN     NaN     NaN     NaN     NaN
86   AACG  1.8665   87  1.8664  1.8663  ...  1.8708     NaN     NaN     NaN     NaN
87   AACG  1.8666   88  1.8665  1.8664  ...  1.8500  1.8708     NaN     NaN     NaN
88   AACG  1.8667   89  1.8666  1.8665  ...  1.8869  1.8500  1.8708     NaN     NaN
89   AACG  1.8668   90  1.8667  1.8666  ...  1.8200  1.8869  1.8500  1.8708     NaN
90   AACG  1.8669   91  1.8668  1.8667  ...  1.8578  1.8200  1.8869  1.8500  1.8708
91   AACG  1.8670   92  1.8669  1.8668  ...  1.8584  1.8578  1.8200  1.8869  1.8500
92   AACG  1.8671   93  1.8670  1.8669  ...  1.8585  1.8584  1.8578  1.8200  1.8869
93   AACG  1.8672   94  1.8671  1.8670  ...  1.8586  1.8585  1.8584  1.8578  1.8200
94   AACG  1.8673   95  1.8672  1.8671  ...  1.8587  1.8586  1.8585  1.8584  1.8578
95   ZYXI  5.2500    1     NaN     NaN  ...     NaN     NaN     NaN     NaN     NaN
96   ZYXI  4.9600    2  5.2500     NaN  ...     NaN     NaN     NaN     NaN     NaN
97   ZYXI  4.9900    3  4.9600  5.2500  ...     NaN     NaN     NaN     NaN     NaN
98   ZYXI  4.9900    4  4.9900  4.9600  ...     NaN     NaN     NaN     NaN     NaN
99   ZYXI  4.9500    5  4.9900  4.9900  ...     NaN     NaN     NaN     NaN     NaN

【讨论】:

  • ZYXI 将从 AACG 获取值:df['Day_'+str(i)] = df['Day_1'].shift(i-1)
  • 通过使用 groupby.transform 选项并在 lambda 函数中使用 shift(i) 来处理它。
  • @JoeFerndz 这现在有效,我认为它比另一个快一点。你能告诉我这是如何工作的,你在想什么,为什么这比我做的要快得多?
  • 我正在遍历从 1 到 90 的数据,因为我们需要为每一列 shift(1)。在我们这样做的同时,我们还应该考虑Symbol。只有当Symbol 相同时才会发生移位。所以我按Symbol 分组,每次迭代将Value 列中的值移动1。
  • @Pygirl 和我都在做同样的事情。 Pygiri 对每个组进行迭代,然后为它移动 90 次。所以两个循环与我的一个循环。这是唯一的区别
【解决方案2】:

尝试使用shift 和pd.concat

N = 5
df_new = pd.DataFrame()
for i,grp in df.groupby('Symbol'):
    l = pd.concat([grp['Value'].shift(i).rename(f'Day_{i}') for i in range(1,N)], axis=1)
    final_df = pd.concat([grp, l], axis=1)
    df_new = df_new.append(final_df)

或

def f(x):
    x['Day-0'] = x['Value']
    for i in range(1,N+1):
        x[f'Day-{i}'] = x[f'Day-{i-1}'].shift()
    x.drop('Day-0', inplace=True ,axis=1)
    return x

final_df = df.groupby('Symbol').apply(f)

**final_df:"

【讨论】:

  • 当Symbol从AACG变为ZYXI时,会将AACG的最后一个不正确的值结转。我们也必须解决这个问题。否则将不符合 OP 要求。这与我面临的挑战相同
  • @JoeFerndz:然后 groupby 符号和每个符号计算移位并将它们垂直连接,在最后一步中,所有组将水平合并。那会做的。我会更新我的答案。感谢您指出了这一点。我没看到
  • 不建议使用 apply ,因为它很慢,但在你的情况下,我想不出任何方法。所以发生的事情就像您按符号进行分组,然后为每个符号计算从 1 到 5(包括)的偏移。该函数 f(x) 完成了该转换部分。
  • @GFG:不要使用Itterrows。使用apply比它好得多。 stackoverflow.com/a/55557758/6660373
  • 赞成您的回答。 apply(f) 也是一个巧妙的技巧。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多