我希望你们中的一些人能找到一点时间来帮助像我这样的初学者。我整个星期都在做这项任务,但找不到解决方案。我理解并完全同意,我必须学习我使用的每个软件包及其组合才能找到正确的解决方案。
完整的任务是将5列(1000行)组合成1个结构列,并将其存储/转换为parquet中的一行(1000列)。但是我坚持将5列组合成1个结构列的问题。
最初,我接收到以下列:列=['date','bitopen','bitover','bithigh','bitlow','tickqty']。我不需要'date'成为结构的一部分。
我所尝试的:
import pyarrow as pa
import pyarrow.parquet as pq
import pandas as pd
选项1-带熊猫的字典
df = pd.read_csv('original.csv')
df2 = df.drop(columns=['date'])
df3 = df2.to_dict('records')
我不能通过熊猫将cript保存到csv或parquet-以下2个命令导致向后转换为熊猫数据帧并单独保存列。
pd.DataFrame(df3).to_csv('test_parquet.csv', index=False)
pd.DataFrame(df3).to_parquet('test2.parquet')
如果我可以将字典用作数据框,接下来我将使用pandas. DataFrame.pivot将行转换为列。接下来,我尝试将cript转换为py箭头表(似乎我也可以将条目保存在列中(1行))。
table = pa.Table.from_pydict({'data', pa.array(df3)})
在上面的行之后,我遇到了一个错误,我找不到解决方案(TypeError:不可解析类型:“pyarrow. lib.StructArray”)。下一步是通过pyarrow将表保存到parmat中。
选项2-通过py箭头构造
在这里,我尝试在parquet中工作以更改模式(或写入新模式)
df = pd.read_csv('original.csv')
df = df.drop(columns=['date'])
df.to_parquet('test.parquet')
table = pq.read_table('test.parquet', columns=['bidopen', 'bidclose', 'bidhigh', 'bidlow', 'tickqty'])
在这里,我阅读了拼花的模式以查看每列的DataType。下面我设置了新模式:
struct = pa.struct([
pa.field('bidopen', pa.float64()),
pa.field('bidclose', pa.float64()),
pa.field('bidhigh', pa.float64()),
pa.field('bidlow', pa.float64()),
pa.field('tickqty', pa.int64())
])
fields = ([pa.field('data', pa.list_(struct))])
schema = pa.schema(fields)
writer = pq.ParquetWriter('test2.parquet', schema)
writer.write_table(table)
writer.close()
我收到一个错误,我也找不到解决方案(ValueError:表模式与用于创建文件的模式不匹配:…),因为我认为它会保存到新提供的模式中。
选项3-py箭头施法
#(the upper part is from the Option 2)
...
schema = pa.schema(fields)
table2 = table.cast(schema)
writer = pq.ParquetWriter('test2.parquet', schema)
writer.write_table(table2)
writer.close()
我收到另一个错误(ValueError:目标模式的字段名与表的字段名不匹配:)。在这里我说-来吧,我正在进行强制转换,因为模式不相同…这没有帮助。
选项4-另一次尝试在加载时将模式从熊猫更改为pyarrow,以便稍后将其保存为拼花
arrays = [['data','data','data','data','data'],['bidopen', 'bidclose','bidhigh','bidlow','tickqty']]
tuples = list(zip(*arrays))
index = pd.MultiIndex.from_tuples(tuples)
df2 = pd.DataFrame(df.values[:, 1:], columns=index)
pa.Schema.from_pandas(df2)
这里我得到了一个错误(属性错误:“列表”对象没有属性“列”),我也找不到解决方案。
选项5-pyspark
对我来说,这是最大的糟糕之处,因为我花了大约3天的时间来“学习”它,因为它应该能够转换为结构体和旋转。但是,后来我发现,如果没有额外的软件包:Hadoop和JavaSDK(它不能免费使用),我就不能在Win10上通过pyspark将数据保存到parket中。因此,我停止了进一步的开发。
对于问题的第一部分,你可以这样做(注意,结构数组。from_arrays需要数组,所以你需要展平分块数组):
fields, arrs = [], []
for column_index in range(table.num_columns):
fields.append(table.field(column_index))
arrs.append(table.column(column_index).flatten()[0].chunks[0])
struct_array = pa.StructArray.from_arrays(arrs, fields=fields)
print(struct_array)
print(struct_array.to_pylist())
样品输出:
-- is_valid: all not null
-- child 0 type: double
[
1.1,
2.2
]
-- child 1 type: double
[
3.3,
4.4
]
-- child 2 type: double
[
5.5,
6.6
]
-- child 3 type: double
[
7.7,
8.8
]
-- child 4 type: int64
[
9,
10
]
[{'bidopen': 1.1, 'bidclose': 3.3, 'bidhigh': 5.5, 'bidlow': 7.7, 'tickqty': 9}, {'bidopen': 2.2, 'bidclose': 4.4, 'bidhigh': 6.6, 'bidlow': 8.8, 'tickqty': 10}]
如果这是你问题的第二部分,我不认为pyarrow可以转置。你可以用熊猫来做转置,但它会是另一个副本。
df = pa.Table.from_arrays([struct_array], ['data']).to_pandas()
print(df.transpose())
样品输出:
0 \
data {'bidopen': 1.1, 'bidclose': 3.3, 'bidhigh': 5...
1
data {'bidopen': 2.2, 'bidclose': 4.4, 'bidhigh': 6...
在这种情况下,输出将始终是具有N列的单行表,每个单元格将是一个结构。