![](/img/trans.png)
[英]Get subset of Pandas df where multiple columns match values from another df
[英]How to get id's from SQLite db into pandas df where the values match but not the data types
我得到一个带有日期时间信息的 dataframe,需要提取日期和时间,将两者都存储在数据库中,取回 ID 并将日期/时间值替换为数据库 ID。
这应该是一个很常见的问题,但我找不到解决办法。
我像这样从 API 收到一个 dataframe(数据在 100 到 >100000 行之间):
data = {
'datetime' : [
'2022-02-23 10:00:00',
'2022-02-23 10:05:00',
'2022-02-23 10:10:00',
'2022-02-23 10:20:30',
'2022-02-23 10:42:00'],
'temp' : [
16.539,
16.98,
16.82001,
17.03,
17.85]
}
df = pd.DataFrame(data)
列的数据类型是:
print(df.dtypes)
datetime object
temp float64
数据必须存储在 SQLite 数据库中。 有一个时间、日期和测量数据的表格,如下所示:
CREATE TABLE Tempvalues (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL UNIQUE,
date_id INTEGER NOT NULL,
time_id INTEGER NOT NULL,
tval REAL
);
CREATE TABLE Time (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL UNIQUE,
time TEXT NOT NULL UNIQUE
);
CREATE TABLE Date (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL UNIQUE,
date TEXT NOT NULL UNIQUE
);
这是我将日期和时间提取到 dataframe 中单独列中的方式:
df['date'] = pd.to_datetime(df['datetime']).dt.date
df['time'] = pd.to_datetime(df['datetime']).dt.time
结果:
datetime temp date time
0 2022-02-23 10:00:00 16.53900 2022-02-23 10:00:00
1 2022-02-23 10:05:00 16.98000 2022-02-23 10:05:00
2 2022-02-23 10:10:00 16.82001 2022-02-23 10:10:00
3 2022-02-23 10:20:30 17.03000 2022-02-23 10:20:30
4 2022-02-23 10:42:00 17.85000 2022-02-23 10:42:00
数据类型:
print(df.dtypes)
datetime object
temp float64
date object
time object
dtype: object
将“日期”和“时间”列存储在数据库中:
df[['date', 'time']].to_sql('Tempdf', conn, index=False)
更新 Time 和 Data.tables 并删除 Tempdf 表:
with conn:
cur.execute("UPDATE Tempdf SET time=STRFTIME('%H:%M:%S', time);")
cur.execute("INSERT OR IGNORE INTO Date (date) SELECT date FROM Tempdf;")
cur.execute("INSERT OR IGNORE INTO Time (time) SELECT time FROM Tempdf;")
cur.execute("DROP TABLE IF EXISTS Tempdf;")
到目前为止,一切正常。 现在我想用数据库中的 Date.id 和 Time.id 值替换 dataframe 中的日期和时间值。 由于我不应该迭代 pandas dataframe,我认为使用 pandas 替换或 map 方法来完成此任务是个好主意。 但它失败了,因为数据类型不匹配:
date_date_id = dict(cur.execute("SELECT date, id FROM Date").fetchall())
time_time_id = dict(cur.execute("SELECT time, id FROM Time").fetchall())
我得到一个字符串和一个 integer:
print(date_date_id)
{'2022-02-23': 1}
使用 pandas map 方法:
df['date'] = df['date'].map(date_date_id)
df['time'] = df['time'].map(time_time_id)
结果:
print(df)
datetime temp date time
0 2022-02-23 10:00:00 16.53900 NaN NaN
1 2022-02-23 10:05:00 16.98000 NaN NaN
2 2022-02-23 10:10:00 16.82001 NaN NaN
3 2022-02-23 10:20:30 17.03000 NaN NaN
4 2022-02-23 10:42:00 17.85000 NaN NaN
数据类型:
datetime object
temp float64
date float64
time float64
dtype: object
当我用花车尝试这个时,它按预期工作:
test_temp = {16.539 : 42, 16.98 : 42}
df['temp'] = df['temp'].map(test_temp)
结果:
datetime temp date time
0 2022-02-23 10:00:00 42.0 2022-02-23 10:00:00
1 2022-02-23 10:05:00 42.0 2022-02-23 10:05:00
2 2022-02-23 10:10:00 NaN 2022-02-23 10:10:00
3 2022-02-23 10:20:30 NaN 2022-02-23 10:20:30
4 2022-02-23 10:42:00 NaN 2022-02-23 10:42:00
所以我假设它不会替换值,因为“日期”和“时间”的数据类型是 object 而不是字符串。
结果是一样的,当替换值指向空列时:
df['date_id'] = df['date'].map(date_date_id)
df['time_id'] = df['time'].map(time_time_id)
结果:
datetime temp date time date_id time_id
0 2022-02-23 10:00:00 16.53900 2022-02-23 10:00:00 NaN NaN
1 2022-02-23 10:05:00 16.98000 2022-02-23 10:05:00 NaN NaN
2 2022-02-23 10:10:00 16.82001 2022-02-23 10:10:00 NaN NaN
3 2022-02-23 10:20:30 17.03000 2022-02-23 10:20:30 NaN NaN
4 2022-02-23 10:42:00 17.85000 2022-02-23 10:42:00 NaN NaN
感觉这是一个应该在sql完全完成的任务,但是我没有做到。 这会在每一行中插入相同的 id,可能是第一个匹配的:
WITH tid (t_id, t_time, df_time) AS
(SELECT Time.id, Time.time, Tempdf.time
FROM Tempdf
JOIN Time
ON Time.time=Tempdf.time)
UPDATE Tempdf
SET time_id = (SELECT t_id FROM tid WHERE t_time = df_time);
如何将 Date.id 和 Time.id 值放入 dataframe 中,使其与“日期”/“时间”列的值相匹配? -> 部分回答
我是否需要以某种方式将数据类型从 object 更改为字符串? 如果是,如何? -> 回答
这是将 dataframe 中的值替换为数据库 ID 的正确方法,还是我走错了路?
有原生的SQLite解决方案吗?
抱歉,我有点迷失了。 如果有任何帮助,我将不胜感激。
通过将“日期”和“时间”列的数据类型更改为字符串,map 方法起作用。
df['date'] = df['date'].astype('str').map(date_date_id)
df['time'] = df['time'].astype('str').map(time_time_id)
但我仍然很感激其他问题的答案。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.