基于日期合并 Pandas 数据框

5

我想基于日期合并两个pandas数据框。问题在于第二个数据框没有包含第一个数据框中的每个日期。我需要使用df1中的每个日期和df2中的最新值。

+-------------+---------------+-------------+
| DataFrame 1 |               |             |
+-------------+---------------+-------------+
| Date        |  Sales loc1   |  Sales loc2 |
| 1/1/17      |  100          |  95         |
| 1/2/17      |  125          |  124        |
| 1/3/17      |  115          |  152        |
| ...         |               |             |
| 2/1/17      |  110          |  111        |
+-------------+---------------+-------------+


+-------------+---------+------+
| DataFrame 2 |         |      |
+-------------+---------+------+
| Date        |  exp    |  loc |
| 1/1/17      |  100    |  1   |
| 1/1/17      |  125    |  2   |
| 2/1/17      |  115    |  1   |
| 2/1/17      |  110    |  2   |
+-------------+---------+------+


+---------------+---------------+--------------+------------+-------------+
| New Dataframe |               |              |            |             |
+---------------+---------------+--------------+------------+-------------+
| Date          |  Sales loc1   |  Sales loc2  |  exp loc1  |  exp loc2   |
| 1/1/17        |  100          |  95          |  100       |  125        |
| 1/2/17        |  125          |  124         |  100       |  125        |
| 1/3/17        |  115          |  152         |  100       |  125        |
| ...           |               |              |            |             |
| 2/1/17        |  110          |  111         |  115       |  110        |
+---------------+---------------+--------------+------------+-------------+

df2中的值将用于多个单元格,直到df2中有新值为止。

非常感谢您的时间。


df2 中是否总是有两组值? - cs95
@cᴏʟᴅsᴘᴇᴇᴅ 每行都有日期、标识符(例如示例中的 loc)和一个值。 - user3029296
是的,但同一日期是否总会有两行数据? - cs95
@cᴏʟᴅsᴘᴇᴇᴅ 不是每次,但有时候 df2 中会出现重复的日期。 - user3029296
1个回答

3

Date有任意数量的相同日期行时,一个通用的解决方案涉及以下几个步骤:

  1. 首先,使用merge合并df1df2
  2. 接下来,使用groupby + apply对数据框进行展平处理
  3. 最后,使用renameadd_prefix对列名进行一些清理

v = df1.merge(df2[['Date', 'exp']])\
       .groupby(df1.columns.tolist())\
       .exp\
       .apply(pd.Series.tolist)

df = pd.DataFrame(v.tolist(), index=v.index)\
       .rename(columns=lambda x: x + 1)\
       .add_prefix('exp loc')\
       .reset_index()

df

     Date  Sales loc1  Sales loc2  exp loc1  exp loc2
0  1/1/17         100          95       100       125
1  2/1/17         110         111       115       110

如果在df2中每个Date只有两个(或者一般情况下恰好有 N 个)数据行的话,下面是另一个可以很好处理的解决方案。

n = 2
v = pd.DataFrame(
     df2.exp.values.reshape(-1, n), 
     index=df2.Date.unique(), 
     columns=range(1, n + 1)
).add_prefix('exp loc')\
 .rename_axis('Date')\
 .reset_index()

现在,只需在 Date 上与 df1 简单合并即可。
df1.merge(v, on='Date')

     Date  Sales loc1  Sales loc2  exp loc1  exp loc2
0  1/1/17         100          95       100       125
1  2/1/17         110         111       115       110

或者,正如@A. Leistra指出的那样,您可能需要使用左外部合并来获得不同类型的结果:
df1.merge(v, how='left', on='Date').ffill()

     Date  Sales loc1  Sales loc2  exp loc1  exp loc2
0  1/1/17         100          95     100.0     125.0
1  1/2/17         125         124     100.0     125.0
2  1/3/17         115         152     100.0     125.0
3  2/1/17         110         111     115.0     110.0

重塑是正确的,但 OP 想要一个左连接,所以你应该使用 df1.merge(v, how='left', on='date').ffill() 代替内连接。 - Silenced Temporarily
@A.Leistra 我明白你的意思。我假设那只是 OP 显示了他们没有包含的数据的输出。 - cs95
谢谢你的帮助。我回到家后会测试这个解决方案。 - user3029296
@user3029296 当然,让我知道进展如何。 - cs95
@cᴏʟᴅsᴘᴇᴇᴅ,我无法使用您的解决方案,因为我有点过于简化了我的问题。我不得不拼凑出一些东西,可能不够优雅,不能在这里发布。由于您的解决方案可能回答了所提出的问题,我将给您正确的答案。感谢您的帮助。 - user3029296

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接