【发布时间】:2020-06-13 23:15:01
【问题描述】:
我在 python 中有以下脚本:
import pyspark
from pyspark.sql import SparkSession
from pyspark.sql.functions import *
from pyspark.sql.types import *
import pandas as pd
import os, shutil
import numpy as np
spark = SparkSession.builder \
.master('local[2]') \
.appName('chapter2') \
.config('spark.jars.packages', 'io.delta:delta-core_2.11:0.4.0') \
.config('spark.executor.memory', '6gb') \
.getOrCreate()
sc = spark.sparkContext
spark.sql("set spark.sql.shuffle.partitions = 1")
delta_path = "folder/with/delta_lake_format"
series = spark.read.format("delta").load(delta_path)
series = series.withColumn("Volume", col("Volume").cast("double"))
series = series.withColumn("Date", to_date(col("Date"), 'MM/dd/yy') )
series.show()
series.printSchema()
我有以下数据框:
+----------+-------+---------+-------+-------+-------+
| Date| Close| Volume| Open| High| Low|
+----------+-------+---------+-------+-------+-------+
|2015-06-01|2109.25|1337694.0| 2109.5|2117.75|2100.25|
|2015-06-02|2106.75|1442673.0| 2106.5| 2116.0| 2094.0|
|2015-06-03| 2116.0|1310989.0|2116.25|2120.75|2106.75|
|2015-06-04| 2099.0|1716475.0| 2099.0| 2116.5|2091.25|
|2015-06-05|2092.25|1459933.0| 2092.0|2102.75| 2083.5|
|2015-06-08|2078.25|1290580.0| 2079.0|2093.25|2076.25|
|2015-06-09| 2080.0|1446234.0| 2080.5|2084.75|2068.75|
|2015-06-10| 2107.0|1664080.0| 2106.0| 2108.0| 2080.0|
|2015-06-11|2109.25|1480391.0|2109.25|2114.75|2103.25|
|2015-06-12| 2093.0|1130566.0| 2094.0|2109.25|2090.25|
|2015-06-15| 2084.0|1077154.0|2083.75|2089.75|2071.25|
|2015-06-16| 2097.5| 790233.0|2097.25|2098.25| 2070.5|
|2015-06-17|2089.25|1577521.0|2088.75|2098.75|2078.75|
|2015-06-18|2114.75|1899198.0| 2114.0|2119.25| 2082.0|
|2015-06-19|2097.75|1236103.0|2097.75|2117.75| 2097.0|
|2015-06-22|2112.75|1095590.0|2113.25| 2122.0| 2103.5|
|2015-06-23| 2116.5| 835219.0| 2117.0| 2120.5|2111.25|
|2015-06-24| 2099.5|1153248.0| 2099.5| 2118.5| 2099.0|
|2015-06-25| 2094.0|1213961.0| 2094.0|2112.75| 2092.0|
|2015-06-26|2095.75|1318744.0|2095.75|2100.75|2086.25|
+----------+-------+---------+-------+-------+-------+
only showing top 20 rows
root
|-- Date: date (nullable = true)
|-- Close: double (nullable = true)
|-- Volume: double (nullable = true)
|-- Open: double (nullable = true)
|-- High: double (nullable = true)
|-- Low: double (nullable = true)
之后我声明了一些我想在 Spark 中执行的 udf:
def get_bt(data):
s = np.sign(np.diff(data))
for i in range(1, len(s)):
if s[i] == 0:
s[i] = s[i-1]
return s
def get_theta_t(bt):
return np.sum(bt)
def ewma(data, window):
alpha = 2 /(window + 1.0)
alpha_rev = 1-alpha
scale = 1/alpha_rev
n = data.shape[0]
r = np.arange(n)
scale_arr = scale**r
offset = data[0]*alpha_rev**(r+1)
pw0 = alpha*alpha_rev**(n-1)
mult = data*pw0*scale_arr
cumsums = mult.cumsum()
out = offset + cumsums*scale_arr[::-1]
return out
schema = series.select('*').schema
column_name = 'Close'; volume_column = 'Volume'; datetimecolumn = 'Date'; initital_T = 100; min_bar = 10; max_bar = 1000;
@pandas_udf(schema, PandasUDFType.GROUPED_MAP)
def process_column(pdf):
#pdf = pdf.set_index(pd.to_datetime(pdf[datetimecolumn], infer_datetime_format = True,format='%Y-%m-%d'))
init_bar = pdf[:initital_T][column_name].values.tolist()
ts = [initital_T]
bts = [bti for bti in get_bt(pdf[column_name])]
res = []
buf_bar, vbuf, T = [], [], 0.
for i in range(initital_T, len(pdf)):
di = pdf.index.values[i]
buf_bar.append(pdf[column_name].iloc[i])
bt = get_bt(buf_bar)
theta_t = get_theta_t(bt)
try:
e_t = ewma(np.array(ts), initital_T / 10)[-1]
e_bt = ewma(np.array(bts), initital_T)[-1]
except:
e_t = np.mean(ts)
e_bt = np.mean(bts)
finally:
if np.isnan(e_bt):
e_bt = np.mean(bts[int(len(bts) * 0.9):])
if np.isnan(e_t):
e_t = np.mean(ts[int(len(ts) * 0.9):])
condition = np.abs(theta_t) >= e_t * np.abs(e_bt)
if (condition or len(buf_bar) > max_bar) and len(buf_bar) >= min_bar:
o = buf_bar[0]
h = np.max(buf_bar)
l = np.min(buf_bar)
c = buf_bar[-1]
v = np.sum(vbuf)
res.append({
datetimecolumn: di,
'Open': o,
'High': h,
'Low': l,
'Close': c,
'Volume': v
})
ts.append(T)
for b in bt:
bts.append(b)
buf_bar = []
vbuf = []
T = 0.
else:
vbuf.append(pdf[volume_column].iloc[i])
T += 1
res = pd.DataFrame(res).set_index(datetimecolumn)
return res
但是当我执行以下操作时:
imbtick_bars = series.withColumn('Date', unix_timestamp(col('Date'), "yyyy-MM-dd").cast("timestamp")) \
.groupBy('Date').apply(process_column)
imbtick_bars.show()
我收到以下错误AttributeError: Can only use .dt accessor with datetimelike values。但是我不知道为什么它不接受“日期”列作为datetype 列(我相信这是错误的根源)。如果有人能指出我的错误或者我应该怎么做,我将不胜感激,因为我已经努力了几天更改代码的某些部分,但我无法找到解决方案。
【问题讨论】:
-
您是否检查过您的日期列不包含任何缺失值?
-
@ndricca 是的,我检查了,没有缺失值
-
目前我在重现您的错误时遇到了一些困难。使用您的示例数据,我得到一个 KeyError 在 pandas_udf 中出现在最后,因为 for 循环
for i in range(initital_T, len(pdf)):导致为空。明天我会尝试模拟更多数据
标签: pandas pyspark apache-spark-sql user-defined-functions