【问题标题】:Creating Dataframe from list of Dictionaries, without using pd.concat()从字典列表创建数据框,而不使用 pd.concat()
【发布时间】:2017-08-23 01:41:59
【问题描述】:

我的数据结构是 numpy 数组的字典,看起来像这样:

metric_one = 
{0: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]),
1: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]),
2: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]),
3: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])}

metric_two = 
{0: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]),
1: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]),
2: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]),
3: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])}

带有以下标签:

['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']

我想要一个如下所示的数据框:

   0  1  2  3
a  0  0  0  0
b  1  1  1  1
c  2  2  2  2
d  3  3  3  3
e  4  4  4  4
f  5  5  5  5
g  6  6  6  6
h  7  7  7  7
i  8  8  8  8
j  9  9  9  9
a  0  0  0  0
b  1  1  1  1
c  2  2  2  2
d  3  3  3  3
e  4  4  4  4
f  5  5  5  5
g  6  6  6  6
h  7  7  7  7
i  8  8  8  8
j  9  9  9  9

我可以通过将每个字典转换为数据帧然后用 pd.concat() 连接它们来做到这一点。但是,这真的很慢,尤其是当要连接的字典增长时(我需要连接大约 20 个)。从分析来看,似乎在连接之前创建单个数据帧实际上花费了大部分时间。因此我想知道是否有更好的方法来做到这一点,例如以一种智能的方式将字典重新排列成一个包含所有字典的大数据结构(可能在一个列表中?可能在一个大字典中?),这样我们就可以通过将这个大数据结构传递给构造函数,只构建一个数据帧。

谢谢!

【问题讨论】:

    标签: python performance pandas dictionary dataframe


    【解决方案1】:

    假设

    metrics = [metric_one, metric_two]
    idx = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
    

    只使用numpy

    lol = [list(np.concatenate([m[i] for m in metrics])) for i in range(4)]
    np.array(lol).T
    pd.DataFrame(np.array(lol).T, idx * len(metrics))
    

    幼稚时间测试

    【讨论】:

    • 谢谢你,就像一个魅力,也快得多!
    【解决方案2】:

    如果您的字典具有相同的形状并具有相同的键,您可以执行以下操作:

    # setup dummy data
    metric_one = {0: np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]),
        1: np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]),
        2: np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]),
        3: np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])}
    
    metric_two = {0: np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]),
        1: np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]),
        2: np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]),
        3: np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])}
    
    labels = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
    
    # store metrics in one list to iterate over
    dicts = [metric_one, metric_two]
    
    # define helper function to concat numpy arrays
    def iter_key(key, dicts):
        return np.concatenate([sub_dict[key] for sub_dict in dicts])
    
    merged = {key: iter_key(key, dicts) for key in metric_one.keys()}
    
    df = pd.DataFrame(merged, index=labels * len(dicts))
    print(df)
    
        0   1   2   3
    a   0   0   0   0
    b   1   1   1   1
    c   2   2   2   2
    d   3   3   3   3
    e   4   4   4   4
    f   5   5   5   5
    g   6   6   6   6
    h   7   7   7   7
    i   8   8   8   8
    j   9   9   9   9
    a   0   0   0   0
    b   1   1   1   1
    c   2   2   2   2
    d   3   3   3   3
    e   4   4   4   4
    f   5   5   5   5
    g   6   6   6   6
    h   7   7   7   7
    i   8   8   8   8
    j   9   9   9   9
    

    首先合并 dicts 比连接 pandas 数据帧更快。下面你会发现 20 个 dicts 的时间安排:

    %%timeit
    dicts = [metric_one, metric_two]  * 10
    def iter_key(key, dicts):
        return np.concatenate([sub_dict[key] for sub_dict in dicts])
    
    merged = {key: iter_key(key, dicts) for key in metric_one.keys()}
    
    df = pd.DataFrame(merged, index=labels * len(dicts))
    
    >>> 1000 loops, best of 3: 630 µs per loop
    

    这里是concat的时间:

    %%timeit
    dicts = [metric_one, metric_two]  * 10
    df = pd.concat([pd.DataFrame(sub_dict, index=labels) for sub_dict in dicts])
    
    >>> 100 loops, best of 3: 13.6 ms per loop
    

    先合并的方法在这里大约快 20 倍。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-08-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-02
      • 1970-01-01
      相关资源
      最近更新 更多