大熊猫:根据时间间隔加入数据帧

时间:2018-08-06 18:30:33

标签: python pandas datetime

我有一个数据框,其中每10分钟有一个datetime列和一个数值:

apply plugin: 'jacoco'

jacoco {
    toolVersion = '0.8.1'
}

tasks.withType(Test) {
    jacoco.includeNoLocationClasses = true
}

task jacocoReport(type: JacocoReport) {

    reports {
        xml.enabled = true
        html.enabled = true
        html.setDestination file("../jacocoHtml")
    }

    def fileFilter = ['**/R.class',
                      '**/R$*.class',
                      '**/BuildConfig.*',
                      '**/Manifest*.*',
                      '**/*Test*.*',
                      'android/**/*.*',
                      '**/*Dagger*.*',
                      '**/Dagger*Component.class',
                      '**/Dagger*Component$Builder.class',
                      '**/*Module.*',
                      '**/*MembersInjector*.*',
                      '**/*_MembersInjector.class',
                      '**/*_Factory.*',
                      '**/*Module_*Factory.class',
                      '**/*_Provide*Factory*.*',
                      '**/**Builder**',
                      '**/**Builder.**']

    sourceDirectories = files(["src/main/java"], ["src/internal/java"], ["src/debug/java"])
    classDirectories = (file("$project.buildDir/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/example").exists()
            ? fileTree(dir: "$project.buildDir/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/example", excludes: fileFilter)
            : fileTree(dir: "$project.buildDir/classes", excludes: fileFilter))
    executionData = fileTree(dir: "$project.buildDir", includes: ["jacoco/*.exec"])
}

另一个带有事件时间表,带有开始时间和结束时间。可能同时发生多个事件:

df1 = pd.DataFrame({'time' : pd.date_range('1/1/2018', periods=20, freq='10min'), 'value' : np.random.randint(2, 20, size=20)})

我想对df1进行左连接,所有事件都在开始时间和结束时间之内。我的输出表应该是:

df2 = pd.DataFrame({'start_time' : ['2018-01-01 00:00:00', '2018-01-01 00:00:00','2018-01-01 01:00:00', '2018-01-01 01:00:00', '2018-01-01 01:00:00', '2018-01-01 02:00:00' ], 'end_time' : ['2018-01-01 01:00:00', '2018-01-01 01:00:00', '2018-01-01 02:00:00','2018-01-01 02:00:00', '2018-01-01 02:00:00', '2018-01-01 03:00:00'], 'event' : ['A', 'B', 'C', 'D', 'E', 'F'] })
df2[['start_time', 'end_time']] = df2.iloc[:,0:2].apply(pd.to_datetime)

我尝试了these SO solutions,但由于重复的时间间隔而失败。

3 个答案:

答案 0 :(得分:3)

设置 (为简便起见,仅使用number_format中的一些条目):

<

您可以使用一些简单明了的列表理解来达到目的。此答案假定您的DataFrame中的所有日期列实际上都是df1类型的

第1步
使用列表理解和简单的间隔检查来查找在特定时间范围内发生的所有事件:

df1 = pd.DataFrame({'time' : pd.date_range('1/1/2018', periods=20, freq='10min'), 'value' : np.random.randint(2, 20, size=20)})
df2 = pd.DataFrame({'start_time' : ['2018-01-01 00:00:00', '2018-01-01 00:00:00','2018-01-01 01:00:00', '2018-01-01 01:00:00', '2018-01-01 01:00:00', '2018-01-01 02:00:00' ], 'end_time' : ['2018-01-01 01:00:00', '2018-01-01 01:00:00', '2018-01-01 02:00:00','2018-01-01 02:00:00', '2018-01-01 02:00:00', '2018-01-01 03:00:00'], 'event' : ['A', 'B', 'C', 'D', 'E', 'F'] })

df1 = df1.sample(5)
df2[['start_time', 'end_time']] = df2.iloc[:,0:2].apply(pd.to_datetime)

第2步

最后,使用另一个列表理解将每个列表从最后一个结果爆炸到新行:

datetime

输出:

packed = list(zip(df2.start_time, df2.end_time, df2.event))
df1['event'] = [[ev for strt, end, ev in packed if strt <= el <= end] for el in df1.time]

                  time  value      event
2  2018-01-01 00:20:00      8     [A, B]
14 2018-01-01 02:20:00     14        [F]
8  2018-01-01 01:20:00      6  [C, D, E]
19 2018-01-01 03:10:00     16         []
4  2018-01-01 00:40:00      7     [A, B]

答案 1 :(得分:0)

我不太确定您的问题,但是如果您尝试加入“属于开始时间和结束时间的事件”,那么听起来您需要类似于SQL中的“介于”运算符。您的数据并不清楚。

Pandas本身没有,但是Pandasql有。它允许您针对数据帧运行sqlite。我认为您需要这样的东西:

import pandasql as ps

sqlcode = '''
select *
from df1
inner join df2 on df1.event=df2.event
where df2.time >= d1.start_time and df2.fdate <= d1.stop_time
'''

newdf = ps.sqldf(sqlcode,locals())

相关问题: Merge pandas dataframes where one value is between two others

答案 2 :(得分:0)

您可以使用df2来创建一个专栏,并始终为每个事件重采样'10min'(例如在df1中),然后使用merge。这是很多操作,因此可能不是最有效的。

df2_manip = (df2.set_index('event').stack().reset_index().set_index(0)
                .groupby('event').resample('10T').ffill().reset_index(1))

df2_manip如下:

                        0 event     level_1
event                                      
A     2018-01-01 00:00:00     A  start_time
A     2018-01-01 00:10:00     A  start_time
A     2018-01-01 00:20:00     A  start_time
A     2018-01-01 00:30:00     A  start_time
A     2018-01-01 00:40:00     A  start_time
A     2018-01-01 00:50:00     A  start_time
A     2018-01-01 01:00:00     A    end_time
B     2018-01-01 00:00:00     B  start_time
B     2018-01-01 00:10:00     B  start_time
B     2018-01-01 00:20:00     B  start_time
B     2018-01-01 00:30:00     B  start_time
...

现在您可以merge

df1 = df1.merge(df2_manip[[0, 'event']].rename(columns={0:'time'}))

您将获得df1

                  time  value event
0  2018-01-01 00:00:00      9     A
1  2018-01-01 00:00:00      9     B
2  2018-01-01 00:10:00     16     A
3  2018-01-01 00:10:00     16     B
...
33 2018-01-01 02:00:00      6     D
34 2018-01-01 02:00:00      6     E
35 2018-01-01 02:00:00      6     F
36 2018-01-01 02:10:00      2     F
37 2018-01-01 02:20:00     18     F
38 2018-01-01 02:30:00     14     F
39 2018-01-01 02:40:00      5     F
40 2018-01-01 02:50:00      3     F
41 2018-01-01 03:00:00      9     F