gpt4 book ai didi

python - 合并具有非唯一索引的多个数据帧

转载 作者:太空宇宙 更新时间:2023-11-03 15:13:12 26 4
gpt4 key购买 nike

我有一堆 Pandas 时间序列。这是一个示例说明(真实数据在每个系列中大约有 100 万个条目):

>>> for s in series:
print s.head()
print
2014-01-01 01:00:00 -0.546404
2014-01-01 01:00:00 -0.791217
2014-01-01 01:00:01 0.117944
2014-01-01 01:00:01 -1.033161
2014-01-01 01:00:02 0.013415
2014-01-01 01:00:02 0.368853
2014-01-01 01:00:02 0.380515
2014-01-01 01:00:02 0.976505
2014-01-01 01:00:02 0.881654
dtype: float64

2014-01-01 01:00:00 -0.111314
2014-01-01 01:00:01 0.792093
2014-01-01 01:00:01 -1.367650
2014-01-01 01:00:02 -0.469194
2014-01-01 01:00:02 0.569606
2014-01-01 01:00:02 -1.777805
dtype: float64

2014-01-01 01:00:00 -0.108123
2014-01-01 01:00:00 -1.518526
2014-01-01 01:00:00 -1.395465
2014-01-01 01:00:01 0.045677
2014-01-01 01:00:01 1.614789
2014-01-01 01:00:01 1.141460
2014-01-01 01:00:02 1.365290
dtype: float64

每个系列的时间都不是唯一的。例如,最后一个系列在 2014-01-01 01:00:00 有 3 个值。第二个系列当时只有一个值。 此外,并非所有时间都需要出现在所有系列中

我的目标是创建一个合并的 DataFrame,其时间是各个时间序列中所有时间的并集。每个时间戳应根据需要重复多次。因此,如果时间戳在上述系列中出现 (2, 0, 3, 4) 次,则时间戳应在生成的 DataFrame< 中重复 4 次(频率的最大值)/。每列的值应“向前填充”。

举个例子,合并上面的结果应该是:

                             c0                c1              c2
2014-01-01 01:00:00 -0.546404 -0.111314 -0.108123
2014-01-01 01:00:00 -0.791217 -0.111314 -1.518526
2014-01-01 01:00:00 -0.791217 -0.111314 -1.395465
2014-01-01 01:00:01 0.117944 0.792093 0.045677
2014-01-01 01:00:01 -1.033161 -1.367650 1.614789
2014-01-01 01:00:01 -1.033161 -1.367650 1.141460
2014-01-01 01:00:02 0.013415 -0.469194 1.365290
2014-01-01 01:00:02 0.368853 0.569606 1.365290
2014-01-01 01:00:02 0.380515 -1.777805 1.365290
2014-01-01 01:00:02 0.976505 -1.777805 1.365290
2014-01-01 01:00:02 0.881654 -1.777805 1.365290

要了解我的真实数据中的大小和“唯一性”:

>>> [len(s.index.unique()) for s in series]
[48617, 48635, 48720, 48620]
>>> len(times)
51043
>>> [len(s) for s in series]
[1143409, 1143758, 1233646, 1242864]

这是我尝试过的:

我可以创建所有唯一时间的联合:

uniques = [s.index.unique() for s in series]
times = uniques[0].union_many(uniques[1:])

我现在可以使用 times 为每个系列编制索引:

series[0].loc[times]

但这似乎在 times 中重复了每个项目的值,这不是我想要的。

我不能使用 times reindex() 系列,因为每个系列的索引不是唯一的。

我可以通过慢速 Python 循环或在 Cython 中完成,但是是否有一种“仅限 pandas”的方式来完成我想做的事情?

我使用以下代码创建了我的示例系列:

def make_series(n=3, rep=(0,5)):
times = pandas.date_range('2014/01/01 01:00:00', periods=n, freq='S')
reps = [random.randint(*rep) for _ in xrange(n)]
dates = []
values = numpy.random.randn(numpy.sum(reps))
for date, rep in zip(times, reps):
dates.extend([date]*rep)
return pandas.Series(data=values, index=dates)

series = [make_series() for _ in xrange(3)]

最佳答案

非常几乎是一个concat:

In [11]: s0 = pd.Series([1, 2, 3], name='s0')

In [12]: s1 = pd.Series([1, 4, 5], name='s1')

In [13]: pd.concat([s0, s1], axis=1)
Out[13]:
s0 s1
0 1 1
1 2 4
2 3 5

但是,concat 无法处理重复索引(它们应该如何合并是不明确的,在您的情况下,您不想以“普通”方式合并它们 - 作为组合)。 .

我认为您将使用 groupby:

In [21]: s0 = pd.Series([1, 2, 3], [0, 0, 1], name='s0')

In [22]: s1 = pd.Series([1, 4, 5], [0, 1, 1], name='s1')

注意:我附加了一个更快的方法,适用于类似 int 的数据类型(如 datetime64)。

我们要添加 cumcounts 的 MultiIndex 级别对于每个项目,我们通过这种方式让索引变得独一无二:

In [23]: s0.groupby(level=0).cumcount()
Out[23]:
0 0
0 1
1 0
dtype: int64

注意:如果不是 DataFrame,我似乎无法将列附加到索引..

In [24]: df0 = pd.DataFrame(s0).set_index(s0.groupby(level=0).cumcount(), append=True)

In [25]: df1 = pd.DataFrame(s1).set_index(s1.groupby(level=0).cumcount(), append=True)

In [26]: df0
Out[26]:
s0
0 0 1
1 2
1 0 3

现在我们可以继续并连接这些:

In [27]: res = pd.concat([df0, df1], axis=1)

In [28]: res
Out[28]:
s0 s1
0 0 1 1
1 2 NaN
1 0 3 4
1 NaN 5

如果您想降低 cumcount 级别:

In [29]: res.index = res.index.droplevel(1)

In [30]: res
Out[30]:
s0 s1
0 1 1
0 2 NaN
1 3 4
1 NaN 5

现在您可以 ffill 以获得所需的结果...(如果您担心不同日期时间的前向填充,您可以按索引分组并 ffill)。


如果每组重复次数的上限合理(我选择 1000,但更高仍然“合理”!,您可以按如下方式使用 Float64Index(当然它看起来更优雅):

s0.index = s0.index + (s0.groupby(level=0)._cumcount_array() / 1000.)
s1.index = s1.index + (s1.groupby(level=0)._cumcount_array() / 1000.)
res = pd.concat([s0, s1], axis=1)
res.index = res.index.values.astype('int64')

注意:我在这里厚颜无耻地使用私有(private)方法,它将 cumcount 作为 numpy 数组返回...
注意 2:这是 pandas 0.14,在 0.13 中你必须将一个 numpy 数组传递给 _cumcount_array 例如np.arange(len(s0))),0.13 之前的版本你运气不好 - 没有 cumcount。

关于python - 合并具有非唯一索引的多个数据帧,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24089922/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com