繁体   English   中英

如何将 id 从 SQLite db 获取到 pandas 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;")

用 id / 我试过的替换 'date', 'time'

到目前为止,一切正常。 现在我想用数据库中的 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM