pandas concat DataFrame对不同的索引

时间:2015-01-14 19:56:44

标签: python pandas merge concat

一般问题

我有一个pandas.DataFrame的任意列表(让我们使用2来保持示例清晰),我希望在{{1}上concat Index那个:

  1. 既不是现有inner的{​​{1}}也不是outer加入
  2. 是一个不同的,单独的DataFrames,但在所有Index
  3. 中包含日期

    例如,请使用以下2个DataFrame'(注意DataFrame形状的差异):

    Index

    我想将这两个In [01]: d1 = pandas.DataFrame( numpy.random.randn(15, 4), columns = ['a', 'b', 'c', 'd'], index = pandas.DatetimeIndex(start = '01/01/2001', freq = 'b', periods = 15) ) In [02]: d2 = pandas.DataFrame( numpy.random.randn(17, 4), columns = ['e', 'f', 'g', 'h'], index = pandas.DatetimeIndex(start = '01/05/2001', freq = 'b', periods = 17) ) 加入交叉的DataFrame,例如Index,在此处构建:

    my_index

    因此,以下结果应与:

    具有相同的结果
    In [03]: ind = range(0, 10, 2)
    In [04]: my_index = d2.index[ind].copy()
    

    个人注意事项

    因为这是一个更大的应用程序,我将有In [05]: d1.loc[my_index, :].join(d2.loc[my_index, :] ) Out[65]: a b c d e f \ 2001-01-05 1.702556 -0.885554 0.766257 -0.731700 -1.071232 1.806680 2001-01-09 -0.968689 -0.700311 1.024988 -0.705764 0.804285 -0.337177 2001-01-11 1.249893 -0.613356 1.975736 -0.093838 0.428004 0.634204 2001-01-15 0.430000 0.502100 0.194092 0.588685 -0.507332 1.404635 2001-01-17 1.005721 0.604771 -2.296667 0.157201 1.583537 1.359332 g h 2001-01-05 -1.183528 1.260880 2001-01-09 0.352487 0.700853 2001-01-11 1.060694 0.040667 2001-01-15 -0.044510 0.565152 2001-01-17 -0.731624 -0.331027 个任意数量的我想:

    1. 使用现有的DataFrame功能,而不是构建我自己的黑客,即pandas等。
    2. 返回reduce( map ( ) )的交叉点视图,而不是创建DataFrame
    3. 的副本

2 个答案:

答案 0 :(得分:2)

我不认为有这样一个开箱即用的Pandas功能。 但是,建立自己的并不难:

def select_join(dfs, index):
    result = dfs[0].reindex(index)
    for df in dfs[1:]:
        result = result.join(df, how='inner')
    return result

例如,

import numpy as np
import pandas as pd
import string
import itertools as IT

columns = iter(string.letters)
dfs = []
for i in range(3):
    d1 = pd.DataFrame( np.random.randn(15, 4), 
                           columns = list(IT.islice(columns, 4)), 
                           index = pd.DatetimeIndex(start = '01/01/2001', 
                                                    freq = 'b', 
                                                    periods = 15))
    dfs.append(d1)

ind = range(0, 10, 2)
my_index = d1.index[ind].copy()
print(select_join(dfs, my_index))

产量

                   a         b         c         d         e         f  \
2001-01-01  0.228430 -1.154375 -0.612703 -2.760826 -0.877355 -0.071581   
2001-01-03  1.452750  1.341027  0.051486  1.231563  0.428353  1.320172   
2001-01-05 -0.966979 -1.997200 -0.376060 -0.692346 -1.689897  0.549653   
2001-01-09 -0.117443 -0.888103  2.092829 -0.467220 -1.083004 -1.443015   
2001-01-11 -0.168980 -0.152663  0.365618  0.444175 -1.472091 -0.578182   

                   g         h         i         j         k         l  
2001-01-01 -0.098758  0.920457 -1.072377 -0.627720  0.223060  0.903130  
2001-01-03  1.962124  1.134501 -0.209813 -2.309090  0.358121  0.655156  
2001-01-05  1.088195 -1.705393 -0.161167 -0.339617  0.945495  0.220701  
2001-01-09  0.970829  1.931192  0.943150 -1.895580  0.815188 -1.485206  
2001-01-11  0.747193 -1.221069 -0.164531 -0.395197 -0.754051  0.922090  

关于第二个考虑:如果index,则无法返回视图 是任意的。 DataFrame将数据(类似dtype)存储在NumPy数组中。什么时候 从NumPy数组中选择任意行,分配新数组的空间 并将行从原始数组复制到新数组中。只有当 选择可以表示为基本切片是返回的视图。这个 NumPy的限制 - 一个非常难以删除的限制! - 冒泡进去 Pandas,导致DataFrames在索引不可表达时返回副本 一个基本的切片。

答案 1 :(得分:1)

不同的方法&他们的时代(完整性)

我接受了@ unutbu的答案,但我认为展示我创建的两个功能(以及@ unutbu' s)及其不同的%timeit值可能很有价值。任何人都想使用它的情况:

创建df_listmy_index

dfs = []
for i in range(5):
    tmp = pandas.DataFrame( numpy.random.randn(1000, 4), 
                            columns = list(itertools.islice(columns, 4)), 
                            index = pandas.DatetimeIndex(start = '01/01/2000', 
                                                         freq = 'b', 
                                                         periods = 1000)
    )

    dfs.append(tmp)

ind = range(0, 1000, 2)
my_index = tmp.index[ind].copy()

3种不同的实施方式

def join_on_index_a(df_list, index):
    return pandas.concat( 
                          map( lambda x: x.reindex(index), df_list), 
                          axis = 1
    )

#@unutbu's implementation
def join_on_index_b(df_list, index):
    result = dfs[0].reindex(index)
    for df in dfs[1:]:
        result = result.join(df, how='inner')
    return result

def join_on_index_c(df_list, index):
    return pandas.concat( map( lambda x: x.loc[index, :], df_list), axis = 1)

使用iPython %timeit

的结果
In [49]: %timeit join_on_index_a(dfs, my_index)
1000 loops, best of 3: 1.85 ms per loop

In [50]: %timeit join_on_index_b(dfs, my_index)
100 loops, best of 3: 1.94 ms per loop

In [51]: %timeit join_on_index_c(dfs, my_index)
100 loops, best of 3: 21.5 ms per loop