如何将 pandas.DataFrame 存储到/从 Redis 中获取?

43

将DataFrame设置到redis中,然后获取它返回的是一个字符串,我无法想出一种方法将这个字符串转换为DataFrame。如何正确执行这两个操作?


1
在将数据放入Redis之前,请使用序列化,并在从Redis读取时进行反序列化。 - Colonel Beauvel
6个回答

59

设置:

redisConn.set("key", df.to_msgpack(compress='zlib'))

获取:

pd.read_msgpack(redisConn.get("key"))

19
截至 pandas 0.25.1 版本,to_msgpack 已被废弃,建议使用 pyarrow。请参考此 Stack Overflow 帖子中的完整示例,了解如何使用 pandas + pyarrow + redis - Shadi
pyarrow 在 2.0.0 版本中弃用了序列化/反序列化功能。详情请见 https://arrow.apache.org/blog/2020/10/22/2.0.0-release/。 - binarymason

9

由于我的数据框中有 Decimal 对象,所以我无法使用 msgpack。相反,我将 pickle 和 zlib 结合在一起,像这样使用,假设有一个名为 df 的数据框和一个本地的 Redis 实例:

import pickle
import redis
import zlib

EXPIRATION_SECONDS = 600

r = redis.StrictRedis(host='localhost', port=6379, db=0)

# Set
r.setex("key", EXPIRATION_SECONDS, zlib.compress( pickle.dumps(df)))

# Get
rehydrated_df = pickle.loads(zlib.decompress(r.get("key")))

这与数据框架无关。

注意事项

  • 使用msgpack的另一个答案更好--如果适用于您,请使用它
  • pickling可能会很危险--您的Redis服务器需要安全,否则您会遇到麻烦

7

to_msgpack在最新版本的Pandas中不可用。

import redis
import pandas as pd

# Create a redis client
redisClient = redis.StrictRedis(host='localhost', port=6379, db=0)
# Create un dataframe
dd = {'ID': ['H576','H577','H578','H600', 'H700'],
  'CD': ['AAAAAAA', 'BBBBB', 'CCCCCC','DDDDDD', 'EEEEEEE']}
df = pd.DataFrame(dd)
data = df.to_json()
redisClient.set('dd', data)
# Retrieve the data
blob = redisClient.get('dd')
df_from_redis = pd.read_json(blob)
df_from_redis.head()

输出


5
使用以下方法对DataFrame进行缓存。
import pyarrow as pa

def cache_df(alias,df):

    pool = redis.ConnectionPool(host='host', port='port', db='db')
    cur = redis.Redis(connection_pool=pool)
    context = pa.default_serialization_context()
    df_compressed =  context.serialize(df).to_buffer().to_pybytes()

    res = cur.set(alias,df_compressed)
    if res == True:
        print('df cached')

要获取缓存的数据框,请使用以下方法。

def get_cached_df(alias):

    pool = redis.ConnectionPool(host='host',port='port', db='db') 
    cur = redis.Redis(connection_pool=pool)
    context = pa.default_serialization_context()
    all_keys = [key.decode("utf-8") for key in cur.keys()]

    if alias in all_keys:   
        result = cur.get(alias)

        dataframe = pd.DataFrame.from_dict(context.deserialize(result))

        return dataframe

    return None

2
import pandas as pd
df = pd.DataFrame([1,2])
redis.setex('df',100,df.to_json())
df = redis.get('df')
df = pd.read_json(df)

4
记得提供解释,而不仅仅是代码。帮助读者理解你的代码为何有效,而不仅仅是如何操作非常重要。特别是当回答一些已有确定答案的老问题时,尤其需要这样做——比如在这种情况下,一个接近四年前被接受且被赞同了很多次的答案。你的方法除了那个建议之外还能提供什么价值?你使用了更快、更干净或更可靠的新技术吗? - Jeremy Caney

0

现在是2021年,这意味着df.to_msgpack()已经被弃用,并且pyarrow在pyarrow 2.0中已经弃用了其自定义序列化功能。(请参见pyarrow的序列化页面中的“任意对象序列化”部分)

这就只剩下可靠的msgpack来序列化对象,以便将它们推送/存储到redis中。

import msgpack
import redis 

# ...Writing to redis (already have data & a redis connection client)
redis_client.set('data_key_name', msgpack.packb(data))

# ...Retrieving from redis
retrieved_data = msgpack.unpackb(redis_client.get('data_key_name'))



你的例子中,“data”是什么? - Mihai Zamfir
这个不起作用,假设数据是Pandas数据框,也许需要澄清你的意思。 - guy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接