使用pandas的python时态连接
我需要用python计算一个“时态连接”。我使用熊猫来阅读和处理数据集。我有两个数据集:使用pandas的python时态连接,python,pandas,Python,Pandas,我需要用python计算一个“时态连接”。我使用熊猫来阅读和处理数据集。我有两个数据集: df: TIME some_features LABEL 1 f -1 2 f -1 3 f -1 5 f -1 6 f -1 7 f -1 10 f
df:
TIME some_features LABEL
1 f -1
2 f -1
3 f -1
5 f -1
6 f -1
7 f -1
10 f -1
11 f -1
13 f -1
15 f -1
labelDf:
TIME_START TIME_STOP LABEL
2 4 0
6 8 1
9 10 2
11 14 1
def temporalJoin(df, labelDf, typeLabel):
count = 0
for index, row in labelDf.iterrows():
for index2, row2 in df.iterrows():
if(row2.TIME > row.TIME_START and row2.TIME < row.TIME_STOP):
df.loc[index2, 'LABEL_'+typeLabel] = row.LABEL_START
count = count +1
print("Label counts: " + str(count) + "\n")
我的脚本的输出必须是df与labelDf的临时连接,因此:
df:
TIME some_features LABEL
1 f -1
2 f 0
3 f 0
5 f -1
6 f 1
7 f 1
10 f 2
11 f 1
13 f 1
15 f -1
现在我使用的是一个非常简单的函数,它基本上必须查看两个数据集的每一行:
df:
TIME some_features LABEL
1 f -1
2 f -1
3 f -1
5 f -1
6 f -1
7 f -1
10 f -1
11 f -1
13 f -1
15 f -1
labelDf:
TIME_START TIME_STOP LABEL
2 4 0
6 8 1
9 10 2
11 14 1
def temporalJoin(df, labelDf, typeLabel):
count = 0
for index, row in labelDf.iterrows():
for index2, row2 in df.iterrows():
if(row2.TIME > row.TIME_START and row2.TIME < row.TIME_STOP):
df.loc[index2, 'LABEL_'+typeLabel] = row.LABEL_START
count = count +1
print("Label counts: " + str(count) + "\n")
def临时连接(df、labelDf、typeLabel):
计数=0
对于索引,labelDf.iterrows()中的行:
对于index2,df.iterrows()中的第2行:
如果(row2.TIME>row.TIME\u开始和row2.TIME
运行这段代码非常慢,我需要对大小大于2GB的数据集运行多次。由于标签的数据集是不重叠的,所以当我匹配标签时,一个好的开始是打破循环,但是,我不喜欢这个解决方案,而且它并不能真正解决问题,因为初始数据集比标签数据集大。
最坏的情况是标签文件,其中包含初始数据集中每个时间戳的标签,因此我想知道是否有方法仅为标签数据集中出现的行选择并运行联接
多谢各位
编辑:我修改了示例以包含两个新的详细信息:
- 首先,时间序列没有固定的间隔。因此,时间=[1,2,3,5,8,11,13]
- 其次,标签文件不是二进制文件,可能会有不可预测的标签数量
- labelDf中的不同间隔可以具有相同的标签
df.set_index('TIME', inplace=True)
df.update(labelDf.reset_index().melt(id_vars=['index', 'LABEL']). \
groupby(['index', 'LABEL'])['value']. \
apply(lambda x: pd.Series(list(range(*list(x))+[max(x)]))). \
reset_index().set_index('value'))
df
# some_features LABEL
# TIME
# 1 f -1.0
# 2 f 0.0
# 3 f 0.0
# 4 f 0.0
# 5 f -1.0
# 6 f 1.0
# 7 f 1.0
说明:
这将在labelDf
上执行一系列重塑操作(没有一个在适当的位置),然后将重塑后的数据帧传递给
首先,熔化labelDf
:
labelDf.melt(id_vars='LABEL')
# LABEL variable value
# 0 0 TIME_START 2
# 1 1 TIME_START 6
# 2 0 TIME_STOP 4
# 3 1 TIME_STOP 8
然后,按标签
分组,选择值
,并应用lambda将时间开始
和时间停止
值放置在列表中,用该列表创建一个范围,并附加列表最大值以使其包含在内(例如so范围(*list([2,4])+[max([2,4])
返回[2,3,4]
),并将结果列表传递给pd.Series
,以将列表拆分为列。因此,该操作的结果是:
labelDf.melt(id_vars='LABEL').groupby('LABEL')['value'].apply( \
lambda x: pd.Series(range(*list(x))+[max(x)]))
…看起来像这样:
# LABEL
# 0 0 2
# 1 3
# 2 4
# 1 0 6
# 1 7
# 2 8
# LABEL level_1
# value
# 2 0 0
# 3 0 1
# 4 0 2
# 6 1 0
# 7 1 1
# 8 1 2
最后的步骤是重置索引,然后将其设置为值
,在本例中,这样传递给.update
的数据帧如下所示:
# LABEL
# 0 0 2
# 1 3
# 2 4
# 1 0 6
# 1 7
# 2 8
# LABEL level_1
# value
# 2 0 0
# 3 0 1
# 4 0 2
# 6 1 0
# 7 1 1
# 8 1 2
请注意,您可以删除
level_1
列,但这不是必需的--因为df
中没有具有此名称的列,它将与update
的结果无关。您好,运行您的解决方案会给出错误:“预期范围最多3个参数,得到10个”。我想补充一件事,老实说,我还没有完全理解你的解决方案,但是,无论如何,初始df不是一系列后续观察,因此可能是时间可以是1,2,3,10,11,20。@GuidoMuscioni听起来像是一个相关的信息,包含在你的问题中。你为什么不修改你的问题,让你的问题更清楚。我已经修改了这个例子,很抱歉遗漏了一些细节。谢谢@GuidoMuscioni。您的labelDf
中是否有出现多次的LABEL
值?我的直觉是,您收到了错误,因为对于多个启动和停止时间范围,相同的标签出现在labelDf
中。是的,可能会发生这种情况。很抱歉,因为您可以看到我的解决方案完全从值中抽象出来,因此,我现在发现了这些东西。