【问题标题】:python assign value to pandas df if falls between range of dates in another df如果落在另一个df中的日期范围之间,python为pandas df赋值
【发布时间】:2017-10-18 14:48:24
【问题描述】:

如果日期介于另一个数据框中的两个日期之间,创建新列并分配值的最佳方法是什么?

例如

dataframe A    
date          values
2017-05-16      x  
2017-04-12      Y


dataframe B    #df contains dates to use to filter and associated id

start            end           id
2017-05-08     2017-05-18      34
2017-04-24     2017-05-08      33
2017-04-03     2017-04-24      32

想要的结果

dataframe A     
date          values    id
2017-05-16      x       34 
2017-04-12      Y       32

我研究了 pd.cut ,它似乎不适用于我想要的,并且编写一个循环来迭代具有多个条件的数据帧似乎效率低下。

【问题讨论】:

  • 我自己没有尝试过,但是对于类似的问题,建议intervaltree package
  • 那些落在“2017-04-24”等边缘的日期呢?应该选择哪个 ID?

标签: python pandas dataframe


【解决方案1】:

使用 IntervalIndex,这是 Pandas 0.20.0 中的新功能。不过,这看起来仍处于实验阶段,因此其他解决方案可能更可靠。

# Get the 'id' column indexed by the 'start'/'end' intervals.
s = pd.Series(df_b['id'].values, pd.IntervalIndex.from_arrays(df_b['start'], df_b['end']))

# Map based on the date of df_a.
df_a['id'] = df_a['date'].map(s)

结果输出:

        date values  id
0 2017-05-16      x  34
1 2017-04-12      Y  32

或者,如果您不介意更改df_b 的索引,您可以直接将其转换为IntervalIndex

# Create an IntervalIndex on df_b.
df_b = df_b.set_index(['start', 'end'])
df_b.index = pd.IntervalIndex.from_tuples(df_b.index)

# Map based on the date of df_a.
df_a['id'] = df_a['date'].map(df_b['id'])

【讨论】:

    【解决方案2】:

    这是一个在 sql 中一步就能完成的非常简单的示例,但在 Pandas 中却没有这么简单。所以附带条件是我不喜欢这种方法,就在这里。

    1. 做一个完整的笛卡尔连接
    2. 过滤到所需的行和列。

    _

    # First Full Outer Join Dataframes 
    # (Requires a Common Column in Pandas Unlike SQL)
    df_A['fake key'] = 1
    df_B['fake key'] = 1
    outer_join = pd.merge(df_A, df_B, how='outer', on='fake key')
    
    # Now Filter Back down to Desired Rows/Columns
    desired_rows    = outer_join.query('date < end and date > start')
    desired_columns = ['date', 'values', 'id']
    
    final = desired_rows[desired_columns]
    final
    

    输出:

            date values  id
    0 2017-05-16      x  34
    5 2017-04-12      y  32
    

    这个答案让我有些不满意的是:

    1. 完全笛卡尔连接的第一步根本不能很好地扩展到大数据
    2. 笛卡尔连接需要一个公共列,因此在这种情况下首先创建该假键列(请参阅this github issue

    【讨论】:

      猜你喜欢
      • 2017-09-26
      • 1970-01-01
      • 2019-08-22
      • 1970-01-01
      • 2013-01-19
      • 2022-01-23
      • 2021-08-25
      • 1970-01-01
      • 2020-09-16
      相关资源
      最近更新 更多