如何解决将列表转换为大熊猫中的数据框时出现AssertionError
我正在尝试将从API抓取的一些数据存储到数据帧,然后将其写入.csv。这通常可以工作,但是脚本有时会因以下错误消息而中断:
AssertionError:传递了16列,传递的数据有17列
有人知道这里发生了什么吗?代码在下面-在“通过”之后会中断
from psaw import PushshiftAPI
import datetime as dt
import pandas as pd
api = PushshiftAPI()
start_epoch=int(dt.datetime(2018,6,2).timestamp())
end_epoch=int(dt.datetime(2018,12,31).timestamp())
subreddit = input('Which subreddit would you like to scrape? ')
submission_results = list(api.search_submissions(after=start_epoch,before=end_epoch,subreddit=subreddit,filter=['id','title','subreddit','num_comments','score','author','is_original content','is_self','stickied','selftext','created_utc','locked','over_18','permalink','upvote_ratio','url'],limit = None))
print ('pass one')
submission_results_df = pd.DataFrame(submission_results)
print ('pass two')
submission_results_df.fillna('NULL')
print('pass three')
submission_results_df.to_csv('D:/CAMER/%s_Submittisons-%s-%s.csv'.format(start_epoch,end_epoch) %(subreddit,start_epoch,end_epoch))
解决方法
我相信最可能的解释是,从查询返回的提交没有全部具有相同数量的字段,并且您构造数据框的方式无法处理此问题。我将提出两种解决方案,然后我将更详细地解释我的想法。
选项1:转换为字典
您可以convert each namedtuple record into a dictionary。这应该更安全,因为熊猫不会假设每个记录都具有相同顺序的相同字段集。如果某些记录有一个额外的字段,那么pandas会为此创建一个列,并为所有其他记录填充NaN。
submission_results_df = pd.DataFrame(result._asdict() for result in submission_results)
选项2:改为使用psaw CLI
我注意到您使用的psaw
库有一个command-line interface,可以直接保存到JSON或CSV。如果您实际上仅使用熊猫将数据转换为CSV,也许这可以避免您的麻烦。
说明
我没有使用Redis的数据直接重现该问题,但是我可以解释一下这里发生的情况。 submission_results
包含在_wrap_thing中创建的namedtuple列表。 (我以前误读了源代码,并认为它们是praw.models.reddit.submission的实例,但这仅在您在构造过程中提供了reddit API对象的情况下才会出现。)
错误消息“声明错误:已传递16列,传递的数据具有17列”似乎来自熊猫_validate_or_indexify_columns,并表明它期望 16列,但已接收到17列的数据列。我不是100%清楚到达这里需要哪个代码路径,但是我在下面提供了一个示例,该示例使用namedtuple
会得到相同的错误。
我认为直接将对象列表传递到DataFrame构造函数中不是一个好主意。构造函数可以采用多种不同的格式解释数据,包括一些似乎没有明确记录的格式。当它获得一个命名元组列表时,它使用 first 命名元组来确定字段名称,然后将每个项目转换为一个列表以提取字段。如果是这样,那么在数据中的某个位置上,至少一个对象具有17个字段而不是16个字段。我不知道psaw
是否做出任何特别保证,以确保所有对象都具有相同数量的字段,甚至即使这些字段相同,这些字段是否也会以相同的顺序出现。
改用namedtuple
复制同一错误消息:
from collections import namedtuple
from pandas import DataFrame
RGB = namedtuple('RGB','red green blue')
RGBA = namedtuple('RGBA','red green blue alpha')
# This works:
d_okay = DataFrame([RGB(1,2,3),RGB(4,5,6)])
# This fails:
d_bad = DataFrame([RGB(1,6),RGBA(7,8,9,0)])
Traceback (most recent call last):
File "/home/annette/anaconda3/lib/python3.7/site-packages/pandas/core/internals/construction.py",line 497,in _list_to_arrays
content,columns,dtype=dtype,coerce_float=coerce_float
File "/home/annette/anaconda3/lib/python3.7/site-packages/pandas/core/internals/construction.py",line 581,in _convert_object_array
f"{len(columns)} columns passed,passed data had "
AssertionError: 3 columns passed,passed data had 4 columns
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "repro.py",line 11,in <module>
d_bad = DataFrame([RGB(1,0)])
File "/home/annette/anaconda3/lib/python3.7/site-packages/pandas/core/frame.py",line 474,in __init__
arrays,columns = to_arrays(data,dtype=dtype)
File "/home/annette/anaconda3/lib/python3.7/site-packages/pandas/core/internals/construction.py",line 461,in to_arrays
return _list_to_arrays(data,coerce_float=coerce_float,line 500,in _list_to_arrays
raise ValueError(e) from e
ValueError: 3 columns passed,passed data had 4 columns
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。