【问题标题】:Finding nearest time in a DataFrame在 DataFrame 中查找最近的时间
【发布时间】:2018-09-15 10:11:51
【问题描述】:

我有两种不同的时间格式数据集

df1 = pd.DataFrame( {'A': [1499503900, 1512522054, 1412525061, 1502527681, 1512532303]})

df2 = pd.DataFrame( {'B' : ['2017-12-15T11:47:58.119Z', '2017-05-31T08:27:41.943Z', '2017-06-05T14:44:56.425Z', '2017-05-30T16:24:03.175Z' , '2017-07-03T10:20:46.333Z', '2017-06-16T10:13:31.535Z' , '2017-12-15T12:26:01.347Z', '2017-06-15T16:00:41.017Z', '2017-11-28T15:25:39.016Z', '2017-08-10T08:48:01.347Z'] })

我需要为第一个数据集中的每个数据找到最近的日期。不管有多远。只需要最近的时间。例如:

1499503900 for '2017-07-03T10:20:46.333Z'
1512522054 for '2017-12-15T12:26:01.347Z'
1412525061 for '2017-05-31T08:27:41.943Z'
1502527681 for '2017-08-10T08:48:01.347Z'
1512532303 for '2017-06-05T14:44:56.425Z'

这里有一些帮助: 这是为了转换为长格式日期:

def time1(date_text):
    date = datetime.datetime.strptime(date_text, "%Y-%m-%dT%H:%M:%S.%fZ") 
    return calendar.timegm(date.utctimetuple())

x = '2017-12-15T12:26:01.347Z'
print(time1(x))

拨出:1513340761

这是为了转换成 ISO 格式:

def time_covert(time):
    seconds_since_epoch = time
    DT.datetime.utcfromtimestamp(seconds_since_epoch)
    return DT.datetime.utcfromtimestamp(seconds_since_epoch).isoformat()

y = 1499503900
print(time_covert(y))

出 = 2017-07-08T08:51:40

任何想法都会非常有用。 提前谢谢大家!

【问题讨论】:

标签: python dataframe time


【解决方案1】:

我想将此作为算法问题而不是特定于熊猫的问题来处理。我的方法是对“df2”系列进行排序,对于 df1 中的每个 DateTime,对排序后的 df2 执行二进制搜索,以获取插入索引。然后检查找到的索引正下方和上方的索引以获得所需的输出。

这是上述过程的代码。

使用标准的 pandas DateTime 以便于比较

df1 = pd.DataFrame( {'A': pd.to_datetime([1499503900, 1512522054, 1412525061, 1502527681, 1512532303], unit='s')})
df2 = pd.DataFrame( {'B' : pd.to_datetime(['2017-12-15T11:47:58.119Z', '2017-05-31T08:27:41.943Z', '2017-06-05T14:44:56.425Z', '2017-05-30T16:24:03.175Z' , '2017-07-03T10:20:46.333Z', '2017-06-16T10:13:31.535Z' , '2017-12-15T12:26:01.347Z', '2017-06-15T16:00:41.017Z', '2017-11-28T15:25:39.016Z', '2017-08-10T08:48:01.347Z']) })

df2按日期排序,二分查找插入位置

df2 = df2.sort_values('B').reset_index(drop=True)
ind = df2['B'].searchsorted(df1['A'])

现在检查插入位置正上方和正下方的索引之间的最小差异

for index, row in df1.iterrows():
    i = ind[index]
    if i not in df2.index:
        print(df2.iloc[i-1]['B'])
    elif i-1 not in df2.index:
        print(df2.iloc[i]['B'])
    else:
        if abs(df2.iloc[i]['B'] - row['A']) > abs(df2.iloc[i-1]['B'] - row['A']):
            print(df2.iloc[i-1]['B'])
        else:
            print(df2.iloc[i]['B'])

测试输出是这些,分别针对 df1 中的每个值。 (注意:请重新检查问题中给出的输出,它们不对应于最小差异)

2017-07-03 10:20:46.333000
2017-11-28 15:25:39.016000
2017-05-30 16:24:03.175000
2017-08-10 08:48:01.347000
2017-11-28 15:25:39.016000

上述过程的时间复杂度为O(NlogN) 用于排序和O(logN) (N = len(df2)) 用于查找每个输出。如果“df1”的大小很大,这将是一个相当快的方法。

【讨论】:

    【解决方案2】:

    这里是一个快速开始:

    def time_covert(time):
        seconds_since_epoch = time
        return datetime.utcfromtimestamp(seconds_since_epoch)
    
    # real time series
    df2['B'] = pd.to_datetime(df2['B'])
    df2.index = df2['B']
    del df2['B']
    
    for a in df1['A']:
        print( time_covert(a))
        i = np.argmin(np.abs(df2.index.to_pydatetime() - time_covert(a)))
        print(df2.iloc[i])
    

    【讨论】:

    • 您好 djangoliv,感谢您的回答。但我有一个小问题,我还没有解决。实际上我正在处理嵌套的 json 数据(大约 24000 个 json 数据)。我试图将你的答案应用在它上面。像这样:
    • for k in range(0,21443,1): df2['rows'][k]['date']=pd.to_datetime(df2['rows'][k][' date'], unit='s') df2.index = df2['rows'][k]['date'] del df2['rows'][k]['date']
    • 但它给了我:必须使用某种集合调用 Index(...),Timestamp('2017-05-08 15:23:56') 已通过。它只读取第一个数据。我已经在搜索它了。它说我需要为索引创建一个数据框。但它已经被创建了。那你怎么看?
    • 没有您的数据文件,我无能为力。但也许你不需要遍历行。
    猜你喜欢
    • 2013-02-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-16
    • 2015-06-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多