【问题标题】:How to convert multi indexed dataframe into a complex structure?如何将多索引数据框转换为复杂结构?
【发布时间】:2018-11-27 07:51:16
【问题描述】:

我的 DataFrame 看起来像这样:

enter image description here

我需要将其转换为如下所示的结构:

{1234: [[(1504010302, 45678), (1504016546, 78908)], [(1506691286,23208)]],
 4576:  [[(1529577322, 789323)], [(1532173522, 1094738), (1532190922, 565980)]]}

所以基本上,我需要使用第一级索引('userID')作为特定用户的所有会话列表的键,并形成不同的特定会话列表,页面浏览量作为基于第二级的元组 -级别索引('session_index')。我试图实现这个解决方案:Convert dataframe to dictionary of list of tuples。但我不知道如何修改它以获得我需要的结构。

from datetime import datetime

# I'm creating the sample of different sessions
iterator = iter([{'user': 1234, 
            'timestamp': 1504010302,
            'pageid': 45678},
            {'user': 1234,
           'timestamp': 1504016546,
           'pageid':78908},
            {'user': 1234,
           'timestamp': 1506691286,
           'pageid':23208}
             ,
           {'user': 4567, 
            'timestamp': 1529577322,
            'pageid': 789323},
           {'user': 4567, 
            'timestamp': 1532173522,
            'pageid': 1094738},
           {'user': 4567, 
            'timestamp': 1532190922,
            'pageid': 565980}])                                      

# Then I'm creating an empty DataFrame
df = pd.DataFrame(columns=['userID', 'session_index', 'timestamp', 'pageid'])

# Then I'm filling the empty DataFrame based on the logic that I need to get in the final structure 
for entry in iterator:
    if not (df.userID == entry['user']).any():
        df = df.append([{'userID': entry['user'], 'session_index': 1, 
                       'timestamp': entry['timestamp'], 'pageid': entry['pageid']}], 
                        ignore_index=True)
    else:
        session_numbers = df[(df.userID == entry['user'])
                              &
                             (df.timestamp.apply(lambda x: abs(datetime.fromtimestamp(x) 
                              - datetime.fromtimestamp(entry['timestamp'])).days*24
                              + abs(datetime.fromtimestamp(x) 
                              - datetime.fromtimestamp(entry['timestamp'])).seconds // 3600  
                              ) <= 24)]        
        if len(session_numbers.session_index.values) == 0:
            df = df.append([{'userID': entry['user'], 'session_index': 
                             df.session_index[df.userID == entry['user']].max() + 1, 
                       'timestamp': entry['timestamp'], 'pageid': entry['pageid']}], 
                        ignore_index=True)
        else:
            df = df.append([{'userID': entry['user'], 'session_index': session_numbers.session_index.values[0], 
                       'timestamp': entry['timestamp'], 'pageid': entry['pageid']}], 
                        ignore_index=True)

# Then I'm setting the Multi Index
df = df.set_index(['userID', 'session_index'])
print(df.index)

# Then I'm trying to get t
new_dict = df.apply(tuple, axis=1)\
    .groupby(level=0)\
    .agg(lambda x: list(x.values))\
    .to_dict()

【问题讨论】:

  • 您的代码中似乎有错字。可以发一下吗?
  • 我粘贴了代码。

标签: python pandas


【解决方案1】:

您的代码很难理解。我以更 Pythonic 的方式重写了它。试试看(它适用于pandas 0.23.0):

rows = [{'user': 1234, 
            'timestamp': 1504010302,
            'pageid': 45678},
            {'user': 1234,
           'timestamp': 1504016546,
           'pageid':78908},
            {'user': 1234,
           'timestamp': 1506691286,
           'pageid':23208}
             ,
           {'user': 4567, 
            'timestamp': 1529577322,
            'pageid': 789323},
           {'user': 4567, 
            'timestamp': 1532173522,
            'pageid': 1094738},
           {'user': 4567, 
            'timestamp': 1532190922,
            'pageid': 565980}]

d = pd.DataFrame(rows)
d["time_diff"] = d.groupby("user")["timestamp"]\
    .rolling(2).apply(lambda x: x[1] - x[0] > 24 * 3600)\
    .fillna(0)\
    .values

d["session_index"] = d.groupby("user")["time_diff"].cumsum()\
    .astype(int) + 1

d.drop("time_diff", axis=1, inplace=True)
d = d.set_index(['user', 'session_index'])

d.apply(lambda x: list(x)[::-1], axis=1)\
    .groupby(level=0)\
    .agg(lambda x: list(x.values))\
    .to_dict()

结果

{1234: [[1504010302, 45678], [1504016546, 78908], [1506691286, 23208]],
 4567: [[1529577322, 789323], [1532173522, 1094738], [1532190922, 565980]]}

【讨论】:

  • 很抱歉提到这一点,但是当我完全运行您的代码时,我仍然得到这个结构:{'pageid': {1234: [45678, 78908, 23208], 4567: [789323, 1094738, 565980]}, 'timestamp': {1234: [1504010302, 1504016546, 1506691286], 4567: [1529577322, 1532173522, 1532190922]}} 无论如何,非常感谢您的帮助!
  • @Elena 请您显示以下脚本的结果:import sys; print("python version:", sys.version); print("pandas version:", pd.__version__)
  • 这里是:python version: 3.5.2 (default, Nov 23 2017, 16:37:01) [GCC 5.4.0 20160609] pandas version: 0.22.0
  • 即使您的代码正在运行,我仍然需要在 mainl 列表中添加一个附加列表结构的另一个结果(基于会话索引){1234: [[(1504010302, 45678), (1504016546, 78908)], [(1506691286,23208)]], 4576: [[(1529577322, 789323)], [(1532173522, 1094738), (1532190922, 565980)]]}
  • @Elena 我在pandas 0.22.0 中看到了与您相同的行为问题是它不会在d.apply(tuple, axis=1) 之后返回一系列元组,而是返回DataFrame。在pandas 0.23.0 中有效。如果需要,您可以使用 sudo -H pip3 install --upgrade pandas 升级您的 pandas 库
猜你喜欢
  • 2020-02-13
  • 1970-01-01
  • 2021-10-08
  • 1970-01-01
  • 2022-01-25
  • 2020-07-11
  • 2013-05-15
  • 1970-01-01
  • 2021-12-08
相关资源
最近更新 更多