python - 如何在支持多种数据格式的 Pandas 中合并日期?

标签 python pandas numpy dataframe datetime

我正在编写一个 Pandas 例程库,它需要能够处理可能具有不同类型的数据框中的日期。具体来说,我得到了很多 datetime.datepandas._libs.tslib.Timestamp 类型的不同组合。据报告(并通过我的测试确认)这与具有多索引设置然后重置的帧有关。 (请参阅我之前的问题 What changes type of date in this pandas code?,它解决了从多索引来回时类型被更改的问题。)

这是一个简短的(但人为设计的)示例:

import pandas as pd
df = pd.DataFrame(
   data={
      'date' : ['2019-01-01', '2019-01-02', '2019-01-03'], 
      'value' : [1, 2, 3], 
      'other' : [11, 12, 13]
   }
)

df.date = pd.to_datetime(df.date).dt.date

print df.head()
         date  other  value
0  2019-01-01     11      1
1  2019-01-02     12      2
2  2019-01-03     13      3

df_reindex = df.set_index(['date','other']).reset_index()
         date  other  value
0  2019-01-01     11      1
1  2019-01-02     12      2
2  2019-01-03     13      3

print pd.merge(df, df_reindex, on='date')
Empty DataFrame
Columns: [date, other_x, value_x, other_y, value_y]
Index: []

print pd.merge(df, df, on='date')
         date  other_x  value_x  other_y  value_y
0  2019-01-01       11        1       11        1
1  2019-01-02       12        2       12        2
2  2019-01-03       13        3       13        3

print pd.merge(df_reindex, df_reindex, on='date')
        date  other_x  value_x  other_y  value_y
0 2019-01-01       11        1       11        1
1 2019-01-02       12        2       12        2
2 2019-01-03       13        3       13        3

print type(df.date[0])
<type 'datetime.date'>

print type(df_reindex.date[0])
<class 'pandas._libs.tslib.Timestamp'>

此处 dfdf_reindex 具有基本相同的数据内容,但是,由于在 set_index 点 Pandas 内部的类型发生了变化,它们之间的合并是空的,而两者中的任何一个与自身之间的“自合并”给出了预期的(尽管,在这里的人为情况下,冗余和微不足道的)结果。

当然,真实案例不会像这样反复无常地设置和重置索引就达到了这一点——真实数据通过多位代码在不同阶段执行具有不同索引要求的不同操作,并且合并是在帧之间进行的有一些不重叠的列。

关于我的另一个关于使用 NumPy 日期时间的问题有评论,但这似乎是徒劳的,因为转换显然会导致两种有问题的数据类型之一,即底层 Pandas 类:

df_numpy = df.copy()

df_numpy.date = df.date.apply(np.datetime64)

print type(df.date[0])
<type 'datetime.date'>

print type(df_numpy.date[0])
<class 'pandas._libs.tslib.Timestamp'>

(更不用说我在现有框架内工作,因此目前可能无法强制所有框架都使用 NumPy 类型而不是 Pandas 类型。)

我需要做的是能够在库代码中合并表,无论它们是否被我无法控制的调用者如此操纵。我作为输入获得的数据框无法更改。我可以复制它们并在副本上实现直接转换(如此处 pandas merge on date column issue ),但框架有时很大,除非没有其他选择,否则我不想复制它们。

有没有办法让合并将它们识别为等效的?如果没有,是否有日期格式的最佳实践选择可以避免此处暴露的转换问题?

最佳答案

Is there a way to get the merge to recognize these as equivalent?

不,不是当前的pandas code :

    # datetimelikes must match exactly
    elif is_datetimelike(lk) and not is_datetimelike(rk):
        raise ValueError(msg)
    elif not is_datetimelike(lk) and is_datetimelike(rk):
        raise ValueError(msg)
    elif is_datetime64tz_dtype(lk) and not is_datetime64tz_dtype(rk):
        raise ValueError(msg)
    elif not is_datetime64tz_dtype(lk) and is_datetime64tz_dtype(rk):
        raise ValueError(msg)

If not, is there a best-practice choice of date format that avoids the conversion issue exposed here?

我从您的问题中了解到,数据框及其数据类型不在您的控制范围内,并且无法更改,因此这个问题不会给我们带来任何帮助。


您需要的是像 SQL 中那样的条件连接。有个老开issue此功能自 2014 年以来没有任何事件。(邀请 PR...)


可能的解决方法是这样的:

def merge_on_date(left, right, on):
    from pandas.core.dtypes.common import is_datetimelike
    try:
        return pd.merge(left, right, on=on)
    except:
        if is_datetimelike(right[on]):
            return pd.merge(left, right.assign(**{on: eval('right[on].dt.date')}), on=on)
        else:
            return pd.merge(left.assign(**{on: eval('left[on].dt.date')}), right, on=on)

结果:

>>> merge_on_date(df, df_reindex, 'date')
         date  value_x  other_x  other_y  value_y
0  2019-01-01        1       11       11        1
1  2019-01-02        2       12       12        2
2  2019-01-03        3       13       13        3
>>> merge_on_date(df_reindex, df, 'date')
         date  other_x  value_x  value_y  other_y
0  2019-01-01       11        1        1       11
1  2019-01-02       12        2        2       12
2  2019-01-03       13        3        3       13

然而,这个大缺点是 assign makes a copy在幕后。

PS:我刚刚看到 pd.merge(df, df_reindex, on='date') 在您的示例中生成了一个空数据框。从版本 0.22.0 开始,这应该引发一个 ValueError。您使用的是什么版本?

关于python - 如何在支持多种数据格式的 Pandas 中合并日期?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58276892/

相关文章:

python - 在 Python 中创建具有多个给定值的掩码数组

python - 用 python 解决一个 3x3 Frog 谜题

c++ - 一次通过 O(n) 时间从大量 URL 列表中查找唯一的 URL

python - 如何将此 csv 数据转换为条形图?

python - 需要将数据框的列值转换为单独的列,并使用 panda 填充每个单元格的计数值

Python pandas 没有属性 ols - 错误(滚动 OLS)

python-3.x - Python Pandas 数据框 Melt

Python Matplotlib - 同一数据文件中的多个系列

python - 具有实时输入和多个控制台的Python子进程

python - 使用谷歌应用程序引擎 urlfetch 来自 mandrill 的验证错误