Добавление фрейма данных панд в электронную таблицу 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')
- Режим записи: сначала очистите существующий рабочий лист =>
ws.clear()
.Второе использованиеset_with_dataframe()
загружая фрейм данных, обратите внимание, чтоresize=True
, который строго устанавливает для строки и столбца на листе значение df.shape. Это поможет позже в методе добавления. - Режим добавления: сначала добавьте строки в соответствии с фреймом данных. Вторая установка параметра
resize=False
поскольку мы добавляем строки иrow=ws.row_count+1
привязка его значения строки для добавления. - Режим чтения (по умолчанию): возвращает фрейм данных
Я столкнулся с той же проблемой, вот что я преобразовал фреймворк в список и использовал
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
, может помочь понять процедуры и решить проблему
Установите библиотеки в своей среде.
Импортируйте библиотеки в скрипт
import pandas as pd import gspread from gspread_dataframe import set_with_dataframe
Создайте учетные данные в консоли Google API .
Добавьте в скрипт следующее, чтобы получить доступ к таблице Google
gc = gspread.service_account(filename='GoogleAPICredentials.json') sh = gc.open_by_key('GoogleSheetID')
Предполагая, что кто-то хочет добавить к первому листу, используйте
0
в
get_worksheet
(для второго листа используйте 1 и т. д.)
worksheet = sh.get_worksheet(0)
Затем, чтобы экспортировать фрейм данных, учитывая, что имя фрейма данных
df
, в таблицу Googleset_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() и сохранить его в этом формате