如何优化更改Pandas Data Frame列中的值

时间:2016-06-30 17:57:33

标签: python pandas

我正在试图找出一只股票将来会从给定的一天变为n天。唯一的问题是,在1000行数据上运行它需要大约一分钟,而且我有数百万行。我认为'滞后'是由这条线引起的:

stocks[0][i][string][line[index]] = adjPctChange(line[adjClose],line[num])

我认为,每次这条线被击中时,可能会复制500个股票的整个3D数据框,但我只是不确定,或者知道如何让它更快。此外,它正在抛出这个警告:

SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame

这是我的代码:

daysForeward = 2
for days in range(1,daysForeward+1):
    string = 'closeShift'+str(days)
    stocks[0][i][string] = stocks[0][i]['adjClose'].shift(days-(days*2))

for line in stocks[0][i].itertuples():
    num = 6 #first closeShift columnb
    for days in range(1,daysForeward+1):
        string = 'closeShift'+str(days)
        stocks[0][i][string][line[index]] = adjPctChange(line[adjClose],line[num])
        num+=1

以下是应用百分比变化之前和之后的数据:

       date     open    close  adjClose  closeShift1  closeShift2
0  19980102  20.3835  20.4417       NaN          NaN     0.984507
1  19980105  20.5097  20.5679       NaN     0.984507     1.034904
2  19980106  20.1408  20.0826  0.984507     1.034904     0.994047
3  19980107  20.1408  20.9950  1.034904     0.994047     0.982926
4  19980108  21.1115  20.0244  0.994047     0.982926     0.989441

       date     open    close  adjClose  closeShift1  closeShift2
0  19980102  20.3835  20.4417       NaN          NaN          NaN
1  19980105  20.5097  20.5679       NaN          NaN          NaN
2  19980106  20.1408  20.0826  0.984507     4.869735     0.959720
3  19980107  20.1408  20.9950  1.034904    -3.947904    -5.022423
4  19980108  21.1115  20.0244  0.994047    -1.118683    -0.463311

一些解释:

[0]中的stocks[0][i]只是为了达到3d数据框中的适当级别,[i]是针对正在迭代的股票中的股票名称更高的循环。

adjClose列只是close的修改版本,而我更喜欢使用close

adjPctChange()是一个自定义百分比变化函数,用于切换公式,使得100到50将产生与50到100相同的结果,因此结果可以被平均并且不会向上倾斜。

def adjPctChange(startPoint, currentPoint):
    if startPoint < currentPoint:
        x = abs(((float(startPoint)-currentPoint)/float(currentPoint))*100.0)
    else:
        x = ((float(currentPoint)-startPoint)/float(startPoint))*100.0    
    return x

感谢任何可以提供帮助的人!

2 个答案:

答案 0 :(得分:2)

你不应该遍历DataFrame;只需使用数组函数执行所有操作。

在:

In [30]: df
Out[30]:
       date     open    close  adjClose  closeShift1  closeShift2
0  19980102  20.3835  20.4417       NaN          NaN     0.984507
1  19980105  20.5097  20.5679       NaN     0.984507     1.034904
2  19980106  20.1408  20.0826  0.984507     1.034904     0.994047
3  19980107  20.1408  20.9950  1.034904     0.994047     0.982926
4  19980108  21.1115  20.0244  0.994047     0.982926     0.989441

数组表示法:

daysForeward = 2
for day in range(1, daysForeward+1):
    column = 'closeShift' + str(day)
    df[column] = (df[column] - df.adjClose) / np.maximum(df[column], df.adjClose) * 100.0

后:

In [33]: df
Out[33]:
       date     open    close  adjClose  closeShift1  closeShift2
0  19980102  20.3835  20.4417       NaN          NaN          NaN
1  19980105  20.5097  20.5679       NaN          NaN          NaN
2  19980106  20.1408  20.0826  0.984507     4.869727     0.959713
3  19980107  20.1408  20.9950  1.034904    -3.947902    -5.022495
4  19980108  21.1115  20.0244  0.994047    -1.118760    -0.463358

答案 1 :(得分:0)

IIUC:

我从这个数据框开始:

print df

       date     open    close  adjclose
0  19980102  20.3835  20.4417  0.984507
1  19980105  20.5097  20.5679  1.034904
2  19980106  20.1408  20.0826  0.994047
3  19980107  20.1408  20.9950  0.982926
4  19980108  21.1115  20.0244  0.989441

然后我创建了这些函数:

def get_lags(s, n):
    return pd.concat([s.shift(i) for i in range(n + 1)],
                     axis=1, keys=range(n + 1))

def get_comps(lags):
    comps = []
    for i, cni in enumerate(lags.columns):
        if i > 0:
            max_ = lags.iloc[:, [0, i]].max(1)
            min_ = lags.iloc[:, [0, i]].min(1)
            comps.append((max_ / min_ - 1) * 100)
    return pd.concat(comps, axis=1)

然后我会滞后并比较它们:

print get_comps(get_lags(df.adjclose, 2))



          0         1
0  0.000000  0.000000
1  5.119009  0.000000
2  4.110168  0.969013
3  1.131418  5.288089
4  0.662817  0.465515

最后,我将它们与df

连接起来
print pd.concat([df, get_comps(get_lags(df.adjclose, 2))], axis=1)

       date     open    close  adjclose         0         1
0  19980102  20.3835  20.4417  0.984507  0.000000  0.000000
1  19980105  20.5097  20.5679  1.034904  5.119009  0.000000
2  19980106  20.1408  20.0826  0.994047  4.110168  0.969013
3  19980107  20.1408  20.9950  0.982926  1.131418  5.288089
4  19980108  21.1115  20.0244  0.989441  0.662817  0.465515

根据需要进行修改。