pandas 在不同的索引上连接 DataFrame
pandas concat DataFrame on different Index
一般问题
我有一个 pandas.DataFrame
的任意列表(让我们使用 2 来保持示例清晰),我想 concat
它们在 Index
上:
- 既不是
inner
也不是现有 DataFrames
的 outer
连接
- 是一个不同的、单独的
Index
,但是 只有 的日期在所有 DataFrame
的 中
例如,采用以下 2 个 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
个人考虑
因为这是一个更大的应用程序,我将有任意数量的 DataFrame
我想要:
- 使用现有的
pandas
功能而不是构建我自己的 hack,即 reduce( map ( ) )
等
- Return 视图
DataFrame
的交集,而不是创建 DataFrame
的副本
我认为没有现成的 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
是不可能return一个观点的
是任意的。 DataFrame 将数据(类似于 dtype)存储在 NumPy 数组中。什么时候
你 select 来自 NumPy 数组的任意行,space 分配了一个新数组
并将行从原始数组复制到新数组中。只有当
selection 可以表示为一个基本切片是一个视图 returned。这个
NumPy 的限制——一个很难消除的限制! --冒泡成
Pandas,当索引无法表示为时,导致数据帧 return 复制
基本切片。
不同的方法及其时间(完整性)
我接受了@unutbu 的回答,但我认为展示我创建的两个函数(和@unutbu 的)及其不同的%timeit
值可能很有价值,以防有人想使用它:
创建 df_list
和 my_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
一般问题
我有一个 pandas.DataFrame
的任意列表(让我们使用 2 来保持示例清晰),我想 concat
它们在 Index
上:
- 既不是
inner
也不是现有DataFrames
的 - 是一个不同的、单独的
Index
,但是 只有 的日期在所有DataFrame
的 中
outer
连接
例如,采用以下 2 个 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
个人考虑
因为这是一个更大的应用程序,我将有任意数量的 DataFrame
我想要:
- 使用现有的
pandas
功能而不是构建我自己的 hack,即reduce( map ( ) )
等 - Return 视图
DataFrame
的交集,而不是创建DataFrame
的副本
我认为没有现成的 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
是不可能return一个观点的
是任意的。 DataFrame 将数据(类似于 dtype)存储在 NumPy 数组中。什么时候
你 select 来自 NumPy 数组的任意行,space 分配了一个新数组
并将行从原始数组复制到新数组中。只有当
selection 可以表示为一个基本切片是一个视图 returned。这个
NumPy 的限制——一个很难消除的限制! --冒泡成
Pandas,当索引无法表示为时,导致数据帧 return 复制
基本切片。
不同的方法及其时间(完整性)
我接受了@unutbu 的回答,但我认为展示我创建的两个函数(和@unutbu 的)及其不同的%timeit
值可能很有价值,以防有人想使用它:
创建 df_list
和 my_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