谷歌表单API和Pandas。API中的数据长度不一致

2024-09-29 21:52:15 发布

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

我正在使用GoogleSheetsAPI获取数据,然后将这些数据传递给Pandas,这样我就可以轻松地处理这些数据

假设我想得到一个包含以下数据的工作表(由于这里没有很好地显示表,所以被描述为JSON对象)

{
  columns: ['Name', 'Age', 'Tlf.' 'Address'],
  data: ['Julie', '35', '12345', '8 Leafy Street']
}

sheets API将返回以下内容:

{
  'range': 'Cases!A1:AE999',
   'majorDimension': 'ROWS',
    'values': 
    [
            ['Name', 'Age', 'Tlf.', 'Address'],
      ['Julie', '35', '12345', '8 Leafy Street']
    ]
}

这很好,让我可以轻松地将列标题和数据传递给Pandas,而无需太多麻烦。我是通过以下方式来做到这一点的:

values = sheets_api_result["values"]
df = pd.DataFrame(values[1:], columns=values[0])
我的问题

如果我有一个类似下表的Gsuite表,它被描述为key:value数据类型

{
  columns: ['Name', 'Age', 'Tlf.' 'Address'],
  data: ['Julie', '35', '', '']
}

我将收到以下答复

{
  'range': 'Cases!A1:AE999',
   'majorDimension': 'ROWS',
    'values': 
    [
            ['Name', 'Age', 'Tlf.', 'Address'],
      ['Julie', '35']
    ]
}

请注意,这两个数组的长度并不不等,返回的不是Nonenull值,而是响应中不存在数据

在我的代码中处理这些数据时,我最终会出现如下错误

ValueError: 4 columns passed, passed data had 2 columns

据我所知,我有两个选择:

  1. 想出一个聪明的方法,在必要时用None填充我的响应
  2. 如果可能,指示API在存在空值的JSON中返回空值,特别是在最后一列完全没有数据的情况下

关于第1点。我想我可以将x{}值附加到列表中,其中x等于length_of_column_heading_array-length_of_data_array。然而,这看起来确实很丑陋,也许有一种更优雅的方式

关于第二点,我还没有找到一个对我有帮助的答案

如果有人对我如何解决这个问题有任何想法,我将非常感激

干杯


Tags: columns数据nameapijsonstreetpandasage
2条回答

如果有人感兴趣,下面是我如何解决这个问题的

首先,我们需要从Sheets API获取所有数据

# define the names of the tabs I want to get
ranges = ['tab1', 'tab2']

# Call the Sheets API
request = service.spreadsheets().values().batchGet(spreadsheetId=document, ranges=ranges,)
response = request.execute()

现在,我想遍历每一列,并确保每一行的列表包含的元素数与第一行包含列标题的元素数相同

# response is the response from google sheets API, 
# and from the code above. It contains column headings
# and data from every row.

# valueRanges is the key to access the data.
def extract_case_data(response, keyword):
    for obj in response["valueRanges"]:
        if keyword in obj["range"]:
            values = pad_data(obj["values"])
            df = pd.DataFrame(values[1:], columns=values[0])
            return df
    return None

最后介绍了数据的填充方法

def pad_data(data: list):

    # build a new array with the column heading data
    # this is the list which we will return
    return_data = [data[0]]

    for row in data[1:]:
        difference = len(data[0]) - len(row)
        new_row = row
        # append None to the lists which have a shorter
        # length than the column heading list
        for count in range(1, difference + 1):
            new_row.append(None)
        return_data.append(new_row)
    return return_data

我当然不是说这是最好或最优雅的解决方案,但它为我做到了

希望这对别人有帮助

同样的想法,也许更简单一些:

获取原始值

result = service.spreadsheets().values().get(spreadsheetId=spreadsheet_id, range=data_range).execute()
raw_values = result.get('values', [])

然后在迭代时完成

for row in raw_values:
    row = row + [''] * (expected_length - len(row))

相关问题 更多 >

    热门问题