将列表转换为数据库中的数据帧时的AssertionError

2024-04-27 19:32:20 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图将从API中获取的一些数据存储到数据框中,然后将其写入.csv。这通常有效,但脚本有时会出现以下错误消息:

AssertionError: 16 columns passed, passed data had 17 columns

有人知道这是怎么回事吗?代码在下面--它在“通过一个”后中断

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))

Tags: columnscsv数据importsubmissiondfdatetimedt
1条回答
网友
1楼 · 发布于 2024-04-27 19:32:20

我认为最有可能的解释是,从查询返回的提交并不都具有相同数量的字段,并且构建数据帧的方式无法处理这一问题。我将建议两种解决方法,然后我将更详细地解释我认为正在发生的事情

选项1:转换为dicts

你可以convert each namedtuple record into a dictionary。这应该更安全,因为这样熊猫就不会假设每个记录都有相同顺序的相同字段集。如果一些记录有一个额外的字段,那么熊猫将为其创建一列,并为所有其他记录填充NaN

submission_results_df = pd.DataFrame(result._asdict() for result in submission_results)

选项2:改用psaw CLI

我注意到您正在使用的psaw库有一个command-line interface可以直接保存为JSON或CSV。如果您实际上只使用pandas将数据转换为CSV,那么这可能会避免您的困难


解释

我没有使用Redis的数据直接重现这个问题,但我可以解释这里发生了什么submission_results包含在_wrap_thing中创建的namedtuple列表。(我之前误读了源代码,认为这些是praw.models.reddit.submission的实例,但这只是在构建过程中提供了reddit API对象的情况下。)

错误消息“断言错误:传递了16列,传递的数据有17列”似乎来自pandas_validate_or_indexify_columns,表明它期望16列,但已收到17列的数据。我不是100%清楚它在这里所采用的代码路径,但我在下面包含了一个使用namedtuple获得相同错误的示例

我认为直接将对象列表传递到DataFrame构造函数不是一个好主意。构造函数可以用多种不同的格式解释数据,包括一些似乎没有明确记录的格式。当它得到一个命名元组列表时,它使用第一个命名元组来确定字段名,然后将每个项转换为一个列表来提取字段。如果这是真的,那么数据中至少有一个对象有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,2,3),RGB(4,5,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,2,3),RGB(4,5,6),RGBA(7,8,9,0)])
  File "/home/annette/anaconda3/lib/python3.7/site-packages/pandas/core/frame.py", line 474, in __init__
    arrays, columns = to_arrays(data, columns, 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, columns, coerce_float=coerce_float, dtype=dtype)
  File "/home/annette/anaconda3/lib/python3.7/site-packages/pandas/core/internals/construction.py", line 500, in _list_to_arrays
    raise ValueError(e) from e
ValueError: 3 columns passed, passed data had 4 columns

相关问题 更多 >