np.where:“ValueError:操作数无法与形状一起广播 (38658637,) (9456,)”

问题描述 投票:0回答:1

我有两个具有两种不同形状的数据框:

  1. df_rts_1 #Shape: (38658637, 7)
  2. df_crsh_rts #Shape: (9456, 6)

我正在尝试使用

np.where
根据特定条件将列值
(df_rts_1['crash'])
更新为等于
1
,如下所示:

  1. df_rts_1['tmc_code']= df_crsh_rts['tmc']
  2. df_rts_1['measurement_tstamp'] is between df_crsh_rts['Start_time'] and df_crsh_rts['Closed_time']

我的代码:

df_rts_1['crash'] = np.where((df_rts_1['tmc_code'].values == df_crsh_rts['tmc'].values) & ((df_rts_1['measurement_tstamp'].values > df_crsh_rts['Start_time'].values) & (df_rts_1['measurement_tstamp'].values > df_crsh_rts['Closed_time'].values)), 1, df_rts_1['crash'])

我收到标题中的错误。我对 Python/数据科学非常陌生。

numpy machine-learning data-processing
1个回答
2
投票

假设您的两个 DataFrame 包含:

  1. df_rts_1

        tmc_code  measurement_tstamp  crash
     0         1 2020-01-03 10:05:00      0
     1         1 2020-01-03 11:00:00      0
     2         1 2020-01-03 12:10:00      0
     3         2 2020-01-03 10:10:00      0
     4         3 2020-01-03 10:05:00      0
    
  2. df_crsh_rts

        tmc          Start_time         Closed_time
     0    1 2020-01-03 10:00:00 2020-01-03 11:00:00
     1    2 2020-01-03 14:00:00 2020-01-03 15:00:00
     2    4 2020-01-03 16:00:00 2020-01-03 18:00:00
    

为了方便评估“之间”条件,让我们创建以下内容 间隔索引

interv = pd.IntervalIndex.from_arrays(df_crsh_rts.Start_time,
    df_crsh_rts.Closed_time, closed='both')

现在,假设我们有来自 df_rts_1 的当前 row,让我们构造 您的情况:

  • “之间”条件可以表示为
    interv.contains(row.measurement_tstamp)
    ,
  • tmc / tmc_code 值的相等性可以表示为 df_crsh_rts.tmc.eq(row.tmc_code)
要检查它们的工作原理,请将

df_rts_1 中的第一行保存为 row 变量:

row = df_rts_1.iloc[0]
并执行这两个条件。

第一个条件生成一个

bool 类型的 Numpy 数组:

array([ True, False, False])
第二个 - 

Series(也是 bool 类型):

0 True 1 False 2 False Name: tmc, dtype: bool
因此要构造最终(单个)

bool值 - 是否是这一行 应该更新它的crash栏,条件是:

(interv.contains(row.measurement_tstamp) & df_crsh_rts.tmc.eq(row.tmc_code)).any()
即上述两个条件的逻辑 

ANDany() - 是否 any 这个合取的元素是True

与您的代码相比,最后的更改是:

    代替
  • where,使用 iloc[...] where 第一个参数(行 选择器)是上面的复合条件,为每一行计算 来自 df_rts_1 (使用列表理解) - 要更新哪些行。
  • 第二个参数只是
  • crash - 要更新的列名称。
  • 1 保存在指定的单元格中。
执行此操作的代码是:

df_rts_1.loc[[ (interv.contains(row.measurement_tstamp) & df_crsh_rts.tmc.eq(row.tmc_code)).any() for row in df_rts_1.itertuples()], 'crash'] = 1
对于我的样本数据,结果是:

tmc_code measurement_tstamp crash 0 1 2020-01-03 10:05:00 1 1 1 2020-01-03 11:00:00 1 2 1 2020-01-03 12:10:00 0 3 2 2020-01-03 10:10:00 0 4 3 2020-01-03 10:05:00 0
编辑评论中的以下问题

问题1。我们是否使用这两个条件的索引来访问和更新 df_rts_1 数据框?

实际上

不是。请注意:

[ (interv.contains(row.measurement_tstamp) & df_crsh_rts.tmc.eq(row.tmc_code)).any() for row in df_rts_1.itertuples() ]
产生 

boollist,其中甚至不包含原始索引。 然后在 .loc[...] 中使用,所以这是 boolean 的情况 索引。此列表中连续的 True / False 元素涉及 来自 df_rts_1 的连续行并说明特定行是否是 待选。

Q2Q3any()在这里做什么? any() 对我们有什么帮助 实现。

查看第一行的示例:

    第一个条件(单独)说明是否
  • measurement_tstamp 在 当前 row 位于 df_crsh_rts, 连续行中的两个日期之间
  • 第二个条件(单独)说明当前
  • row 是否有匹配 tmc 位于 df_crsh_rts 的连续行中。
我们要求

同一行必须满足两个这些条件 来自 df_crsh_rts,因此 & 加入它们。

但请注意:

  • condition_1 & condition_2 产生 bool 类型的 Series - 是否 连续行满足两个部分条件:

    0 True 1 False 2 False Name: tmc, dtype: bool
    
    
  • 但是我们不需要任何

    Seriesbool。我们需要一个 single bool, 说明上述结果是否至少包含一个True值。

就是这个转变(从

bool Seriessingle bool) 由 any() 执行。

编辑2

由于你的数据量很大,我想出了另一个,可能更快 解决方案。这个想法是:

  • df_rts_1 by tmc_code,
  • 仅检查
  • Between 条件与当前间隔的关系 tmc.
  • 为了更快地选择适当的间隔,请使用辅助
  • Seriestmc 索引的间隔(通过索引搜索更快)。
为此,请定义以下函数,应用于每个组:

def newCrash(grp): # Intervals for the current tmc_code wrk = intrv[intrv.index == grp.iloc[0,0]] if wrk.empty: return grp.crash # Nothing found - no change wrkInd = pd.IntervalIndex(wrk) return grp.crash.mask([ wrkInd.contains(ts).any() for ts in grp.measurement_tstamp ], 1)
然后创建辅助

系列

intrv = pd.Series(pd.IntervalIndex.from_arrays(df_crsh_rts.Start_time, df_crsh_rts.Closed_time, closed='both'), index=df_crsh_rts.tmc)
最后运行

crash列的更新:

df_rts_1.crash = df_rts_1.groupby('tmc_code', sort=False).\ apply(newCrash).reset_index(level=0, drop=True)
对于您的(非常小的)样本数据,此解决方案运行速度较慢。

但是当我将

df_rts_1 的大小增加到 40 行后,这个解决方案 工作速度更快一点。

如果进一步增大

df_rts_1的大小,速度上的差异 应该更大(有利于第二种解决方案)。

在样本上检查两种解决方案(原始解决方案和此解决方案)。 100,000 行 来自

df_rts_1 并写出这两个解决方案的执行时间。

© www.soinside.com 2019 - 2024. All rights reserved.