提问者:小点点

柱子结构镶木地板由py箭头和(或)熊猫在Python


我希望你们中的一些人能找到一点时间来帮助像我这样的初学者。我整个星期都在做这项任务,但找不到解决方案。我理解并完全同意,我必须学习我使用的每个软件包及其组合才能找到正确的解决方案。

完整的任务是将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中。因此,我停止了进一步的开发。


共1个答案

匿名用户

对于问题的第一部分,你可以这样做(注意,结构数组。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列的单行表,每个单元格将是一个结构。