我正在学习SQLAlchemy并被卡住。 我有一个SQL表(table1)有两个字段:'name'和'other_names'
我有一个包含两列的excel文件:
first_name alias
paul patrick
john joe
simon simone
john joey
john jo
我想将excel文件读到我的table1中,使其看起来像这样(即同一行的所有别名都在一行上):
paul patrick
john joe,joey,jo
simon simone
这是我试图做的想法。我尝试过的代码(带有注释):
for line in open('file.txt', 'r'): #for each line in the excel file
line = line.strip().split('\t') #split each line with a name and alias
first_name = line[0] #first name is the name before the tab
alias = line[1] #alias is the name after the tab
instance =
Session.query(session,tbs['table1'].name).filter_by(name=first_name) #look through the database table, by name field, and see if the first name is there
list_instance = [x[0] for x in instance] #make a list of first names already in database table
if first_name not in list_instance: #if the excel first name is not in the database table
alias_list = [] #make an empty list
alias_list.append(alias) #append the alias
name_obj = lib.get_or_create( #small function to make db object
session,
tbs["table1"],
name = first_name, #add first name to the name field
other_names = alias_list # add alias list to the other_names field
)
elif first_name in list_instance: #elif first name already in db
alias_list.append(alias) #append the alias to the alias list made above
name_obj = lib.get_or_create(
session,
tbs["table1"],
name = first_name,
other_names = alias_list #create object as before, but use updated alias list
)
问题是我可以使上面的代码无错误运行,而且输出不是附加列表,它只是一个数据库表,看起来像excel文件;即
name alias
paul patrick
john joe
simon simone
john joey
john jo
有人可以指出我要去哪里,特别是如何修改此代码?如果问题不清楚,请让我知道,我试图将其作为一个简单的例子。具体来说,我如何初始化并添加到列表中作为SQLalchemy db表中的字段条目。
更新1:我已根据以下同类建议更新了我的代码。但是我仍然有问题。这是完整的目标,代码和测试文件: 目的:
我在数据库中有一个表(进入表的测试文件请参见下文),该表有两个字段,名称(拉丁名称,例如智人)和其他名称(常见名称,例如人,人)。我想更新表中的字段(其他名称),所以不要:
Rana rugosa human
Rana rugosa man
Rana rugosa frog
Rana rugosa cow
我有:
Rana rugosa human,man,frog,cow
test_data文件如下所示:
origin_organism common_name tested_organism
Rana rugosa human -
Rana rugosa man -
Rana rugosa frog homo sapiens
Rana rugosa cow Rana rugosa
Rana rugosa frog Rana rugosa
Rana rugosa frog -
Rana rugosa frog -
Rana rugosa frog homo sapiens
- - -
- - homo sapiens
- - -
- - -
- - -
- - -
streptococcus pneumoniae - -
代码:
import sys
from sqlalchemy.orm import *
from sqlalchemy import *
from dbn.sqlalchemy_module import lib
import pd
engine = lib.get_engine(user="user", psw="pwd", db="db", db_host="111.111.111.11")
Base = lib.get_automapped_base(engine)
session = Session(engine)
tbs = lib.get_mapped_classes(Base)
session.rollback()
df = pd.read_excel('test_data.xlsx', sheet_name = 'test2')
for index, row in df.iterrows():
origin_latin_name = row['origin_organism'].strip().lower()
other_names_name = row['common_name'].strip().lower()
tested_species = row['tested_organism'].strip().lower()
if origin_latin_name not in [None, "None", "", "-"]:
instance = [x[0] for x in Session.query(session,tbs['species'].name).filter_by(name=origin_latin_name).all()]
if origin_latin_name not in instance:
origin_species = lib.get_or_create(
session,
tbs["species"],
name = origin_latin_name,
other_names = other_names_name
)
elif origin_latin_name in instance:
other_names_query = Session.query(session,tbs['species'].other_names).filter_by(name=origin_latin_name)
other_names_query_list = [x for x in other_names_query]
original_list2 = list(set([y for y in x[0].split(',') for x in other_names_query_list]))
if other_names_name not in original_list2:
original_list2.append(other_names_name)
new_list = ','.join(original_list2)
new_names = {'other_names':','.join(original_list2)}
origin_species = lib.get_or_create(
session,
tbs["species"],
name = origin_latin_name,
other_names = new_list
)
elif语句中的部分无效。我遇到了两个问题:
(1)我得到的最新错误: NameError:名称“ new_list”未定义
(2)我遇到的另一个错误是我还有另外一张桌子
map1 = lib.get_or_create(
session,
tbs["map1"],
age_id_id = age,
name_id_id = origin_species.id
)
...并且它说无法找到origin_species,但是我认为这与elif语句相关联,以某种方式无法正确更新origin_species对象。
如果有人可以帮助,我将不胜感激。
答案 0 :(得分:3)
简单的错误。您没有列出清单。我不确定为什么它们会以不同的行结尾,但是,我将更改以下内容,因为目前我看不到将名称拆分到列表中的位置,我所看到的只是使用以下命令将字符串分配给列表追加。
alias_list = alias.split(',')
也可能是:
alias_list = line[1].split(',')
输出:
alias_list: ['Name1','Name2','Name3']
当前您的代码输出:
alias_list = ['Name1,Name2,Name3']
虽然从技术上讲它是按数据类型的列表,但对于您要使用的方式而言,它是毫无价值的列表。这是因为alias_list[0]
将返回整个字符串,而不是'Name1'
警告语:
您的代码不必要地创建了一个列表。您的数据库中不需要列表,使用读取excel文件时评估的字符串就可以轻松实现自己的目标。
IMHO应该做的是将名称字符串存储为一个完整的字符串,然后,如果需要查询某人的别名,那么可以在另一侧拆分该字符串吗?
答案 1 :(得分:0)
如果对熊猫数据框使用groupby语句,则可以轻松地做到这一点。代码未经测试,让我知道是否存在错误
import sys
from sqlalchemy.orm import *
from sqlalchemy import *
from dbn.sqlalchemy_module import lib
import pd
engine = lib.get_engine(user="user", psw="pwd", db="db", db_host="111.111.111.11")
###Get test data
added_df = pd.read_excel('test_data.xlsx', sheet_name = 'test2')
###Get current database as a pandas object
my_current_df = pd.read_sql_table(
"table1", engine)
#Now group by origin organism
gb = added_df.groupby('origin_organism')
#For every member that had the same origin organism, return it as a comma seperated list into a new dataframe
df = pd.DataFrame(gb.alias.apply(lambda x: ",".join(x)))
#Now append that dataframe onto the one that came from the database
my_current_df.append(df)
#NOw return that dataframe back to the database
my_current_df.to_sql(
name='table1',
con=engine,
if_exists='replace')