Добавление фрейма данных панд в электронную таблицу Google

Случай: Мой сценарий возвращает фрейм данных, который необходимо добавить в существующую электронную таблицу Google в виде новых строк данных. На данный момент я добавляю фрейм данных в виде нескольких отдельных строк с помощью маскирования.

Мой код:

import gspread
import pandas as pd
df = pd.DataFrame()

# After some processing a non-empty data frame has been created.

output_conn = gc.open("SheetName").worksheet("xyz")

# Here 'SheetName' is google spreadsheet and 'xyz' is sheet in the workbook

for i, row in df.iterrows():
    output_conn.append_row(row)

Есть ли способ добавить весь фрейм данных, а не несколько отдельных строк?

10 ответов

Решение

Я могу порекомендовать gspread-dataframe:

import gspread_dataframe as gd

# Connecting with `gspread` here

ws = gc.open("SheetName").worksheet("xyz")
existing = gd.get_as_dataframe(ws)
updated = existing.append(your_new_data)
gd.set_with_dataframe(ws, updated)

Вот код для записи, добавления (без загрузки существующего листа в память) и чтения в листы Google.

import gspread_dataframe as gd
import gspread as gs
gc = gs.service_account(filename="your/cred/file.json")

def export_to_sheets(worksheet_name,df,mode='r'):
    ws = gc.open("SHEET_NAME").worksheet("worksheet_name")
    if(mode=='w'):
        ws.clear()
        gd.set_with_dataframe(worksheet=ws,dataframe=df,include_index=False,include_column_header=True,resize=True)
        return True
    elif(mode=='a'):
        ws.add_rows(df.shape[0])
        gd.set_with_dataframe(worksheet=ws,dataframe=df,include_index=False,include_column_header=False,row=ws.row_count+1,resize=False)
        return True
    else:
        return gd.get_as_dataframe(worksheet=ws)
    
df = pd.DataFrame.from_records([{'a': i, 'b': i * 2} for i in range(100)])
export_to_sheets("SHEET_NAME",df,'a')

  1. Режим записи: сначала очистите существующий рабочий лист => ws.clear().Второе использование set_with_dataframe() загружая фрейм данных, обратите внимание, что resize=True, который строго устанавливает для строки и столбца на листе значение df.shape. Это поможет позже в методе добавления.
  2. Режим добавления: сначала добавьте строки в соответствии с фреймом данных. Вторая установка параметраresize=False поскольку мы добавляем строки и row=ws.row_count+1 привязка его значения строки для добавления.
  3. Режим чтения (по умолчанию): возвращает фрейм данных

Я столкнулся с той же проблемой, вот что я преобразовал фреймворк в список и использовал append_rows()

          gc = gspread.service_account(filename="credentials.json")
    sh = gc.open_by_key('<your_key>')
    ws = sh.sheet1
    
    ##data is the original data frame
    data_list = data.values.tolist()
    
    ws.append_rows(data_list)

Следующий подход с использованием gspread, может помочь понять процедуры и решить проблему

  1. Установите библиотеки в своей среде.

  2. Импортируйте библиотеки в скрипт

            import pandas as pd
    import gspread
    from gspread_dataframe import set_with_dataframe
    
  3. Создайте учетные данные в консоли Google API .

  4. Добавьте в скрипт следующее, чтобы получить доступ к таблице Google

            gc = gspread.service_account(filename='GoogleAPICredentials.json')
    sh = gc.open_by_key('GoogleSheetID')
    

Предполагая, что кто-то хочет добавить к первому листу, используйте 0 в get_worksheet (для второго листа используйте 1 и т. д.)

      worksheet = sh.get_worksheet(0)
  1. Затем, чтобы экспортировать фрейм данных, учитывая, что имя фрейма данных df, в таблицу Google

            set_with_dataframe(worksheet, df)
    

Я пришел к следующему решению. Он не перезаписывает текущие данные, а просто добавляет весь DataFrame pandasdf в конец листа с именем sheet в таблице с именем spread_sheet.

import gspread
from google.auth.transport.requests import AuthorizedSession
from oauth2client.service_account import ServiceAccountCredentials

def append_df_to_gs(df, spread_sheet:str, sheet_name:str):
    scopes = [
        'https://spreadsheets.google.com/feeds',
        'https://www.googleapis.com/auth/drive',
    ]
    credentials = ServiceAccountCredentials.from_json_keyfile_name(
        path_to_credentials,
        scopes=scopes
    )
    gsc = gspread.authorize(credentials)
    sheet = gsc.open(spread_sheet)
    params = {'valueInputOption': 'USER_ENTERED'}
    body = {'values': df.values.tolist()}
    sheet.values_append(f'{sheet_name:str}!A1:G1', params, body)

Для параметров valueInputOptionпожалуйста, проконсультируйтесь с этим. я использовалUSER_ENTERED здесь, поскольку мне нужно, чтобы некоторые формулы действовали после добавления данных в Google Таблицы.

Я придумал следующее решение, используя оператор try/catch: если электронная таблица не существует, он создаст ее для вас и установит фрейм данных, иначе он добавит ее.

      def load_to_sheet(conn_sheet, spreadsheet_name, df):
try:
    worksheet = conn_sheet.worksheet(spreadsheet_name)
    worksheet.add_rows(df.shape[0])
    set_with_dataframe(worksheet=worksheet, row=worksheet.row_count, dataframe=df, include_index=False,
                       include_column_header=False,
                       resize=False)
except Exception:
    worksheet = conn_sheet.add_worksheet(title=spreadsheet_name, rows=100, cols=100)
    set_with_dataframe(worksheet=worksheet, dataframe=df, include_index=False, include_column_header=True,
                       resize=True)
ws = gc.open("sheet title").worksheet("ws")

gd.set_with_dataframe(ws, dataframe)

# просто преобразуйте фрейм данных в таблицу Google

Для следующего не требуются внешние библиотеки, кроме gspread:

      worksheet.update([dataframe.columns.values.tolist()] + dataframe.values.tolist())

Улучшение решения, данного Даршем Шукла

      def append_df_to_sheet(g_spread_name, sheet_name, df):
    
    wks = gd.set_with_dataframe(worksheet= self.gc.open(g_spread_name).worksheet(sheet_name) # get the sheet
    append_row = wks.row_count+1 # position where to append
    wks.add_rows(df.shape[0]) # add rows to avoid API range error
    gd.set_with_dataframe(worksheet= self.gc.open(self.g_spread_name).worksheet(sheet_name), # refresh the sheet   
                dataframe=df,
                include_index=False,
                include_column_header=False,
                row = append_row,
                resize=False)
    return True

Это позволяет избежать ошибки

      gspread.exceptions.APIError: {'code': 400, 'message': 'Range (test!A999:B1001) exceeds grid limits. Max rows: 998, max columns: 26', 'status': 'INVALID_ARGUMENT'}

Если электронная таблица Google принимает формат.csv, то вы можете преобразовать файл данных pandas в csv с помощью df.to_csv() и сохранить его в этом формате

Другие вопросы по тегам