【问题标题】:Adding values to pandas DataFrame given condition在给定条件下向 pandas DataFrame 添加值
【发布时间】:2019-01-21 20:30:31
【问题描述】:

我一直在努力寻找最有效的方法来做到这一点。 假设我有一个 DataFrame df1,它看起来像:

   time_start  time_end    
0  1548102229  1548102232  
1  1548102239  1548102242 
2  1548102249  1548102252
3  1548102259  1548102262

和另一个看起来像的 DataFrame df2:

   timestamp   state    
0  1548102231  A  
1  1548102241  A 
2  1548102248  B
3  1548102251  B

在 df2['timestamp'] 介于 df1['time_start'] 和 df1['time_end'] 之间的条件下,有没有办法将“状态”添加到 df1:

   time_start  time_end    state
0  1548102229  1548102232  A
1  1548102239  1548102242  A
2  1548102249  1548102252  N/A
3  1548102259  1548102262  B

【问题讨论】:

  • 这是一个很好的问题,我实际上没有遇到过这种情况,但它最终肯定会发生。如果是这样,我想采取第一种状态。

标签: python pandas dataframe


【解决方案1】:

使用IntervalIndexget_indexer,然后我们在.loc之后赋值

idx=pd.IntervalIndex.from_arrays(df1['time_start'], df1['time_end'], closed='both')
indexmatch=idx.get_indexer(df2.timestamp)
df1['New']=df2.loc[indexmatch,'state'].values
df1
   time_start    time_end  New
0  1548102229  1548102232    A
1  1548102239  1548102242    A
2  1548102249  1548102252  NaN
3  1548102259  1548102262    B

更新

idx=pd.IntervalIndex.from_arrays(df1['time_start'], df1['time_end'], closed='both')
indexmatch=idx.get_indexer(df2.timestamp)
dfcopy=df1.copy()
df1=df1.loc[indexmatch]
df1['New']=df2.loc[indexmatch,'state'].values
df1.groupby(['time_start','time_end'],as_index=False).New.sum().combine_first(dfcopy)

【讨论】:

  • 如果 df2 的长度与 df1 不同,并且我试图查找 df2 中是否有一个时间戳值介于 time_start 和 time_end 之间以填充 df1 中的状态,该怎么办?我确信在任何给定的时间段内只存在一种状态,即 A 或 B,但该状态可以记录多次。
  • 这已经非常接近了。我只有最后一行的问题: df1.groupby(['time_start','time_end'],as_index=False).New.sum().combine_first(dfcopy) sum() 部分给了我一个意想不到的结果.如果 df1['New'] 是一个整数,它会总结数量或出现的状态。如果它是一个字符串,它会做一个字符串总和,所以如果有超过 1 个记录的状态,它会给我像 AAA 这样的值,如果字符串或者如果状态 A=1,它会给我 3。试图不加总和但似乎combine_first 不喜欢它。
  • 没关系,我刚刚结束了 df1.groupby(['time_start','time_end'],as_index=False).first() 我认为 combine_first(dfcopy) 是没有必要的。
【解决方案2】:

使用np.less_equalnp.greater_equal outer ufuncs

c = np.less_equal.outer(df2.timestamp, df.time_end) & \
    np.greater_equal.outer(df2.timestamp, df.time_start)

df['state'] = df2.state.values[c.argmax(1)]

然后更正所有False 结果

df.loc[~c.any(1), 'state'] = np.nan

    time_start  time_end    state
0   1548102229  1548102232  A
1   1548102239  1548102242  A
2   1548102249  1548102252  NaN
3   1548102259  1548102262  B

【讨论】:

  • 我想你的方法的问题是一样的:如果 df2 的长度与 df1 不同,我试图找出 df2 中是否有一个时间戳会落在 time_start 之间的值和 time_end 填充 df1 中的状态?我确信在任何给定的时间段内只存在一种状态,即 A 或 B,但该状态可以记录多次。
猜你喜欢
  • 2020-12-31
  • 1970-01-01
  • 2017-08-06
  • 2013-03-01
  • 2017-11-30
  • 1970-01-01
  • 2015-09-04
  • 1970-01-01
相关资源
最近更新 更多