np.where: "ValueError: operands could not be broadcast together with shapes (38658637,) (9456,)"
np.where: "ValueError: operands could not be broadcast together with shapes (38658637,) (9456,)"
我有两个具有两种不同形状的数据框:
df_rts_1 #Shape: (38658637, 7)
df_crsh_rts #Shape: (9456, 6)
我正在尝试使用 np.where 来更新列值 (df_rts_1['crash'])根据一定条件等于1
如下:
df_rts_1['tmc_code']= df_crsh_rts['tmc']
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/data 科学还很陌生,因此非常感谢您的帮助。
假设你的两个 DataFrame 都包含:
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
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 的当前 行,让我们构建
您的情况:
- “介于”条件可以表示为
interv.contains(row.measurement_tstamp)
,
- tmc / tmc_code值的等式可以表示为
df_crsh_rts.tmc.eq(row.tmc_code)
.
要检查它们是如何工作的,将 df_rts_1 的第一行保存为 行 变量:
row = df_rts_1.iloc[0]
并执行两个条件。
第一个条件生成一个 Numpy 数组 bool 类型:
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()
即以上两个条件的逻辑 AND 和 any() - 是否 any
这个连词的元素是 True.
与您的代码相比,最后的变化是:
- 而不是 where,使用 iloc[...] 其中第一个参数(行
selector) 是上面的复合条件,为每一行计算
来自 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
在评论中编辑以下问题
Q1。我们是否使用来自两个条件的索引来访问和更新
df_rts_1 数据框?
实际上不是。注意:
[ (interv.contains(row.measurement_tstamp) &
df_crsh_rts.tmc.eq(row.tmc_code)).any() for row in df_rts_1.itertuples() ]
产生一个 list of bools,它甚至不包含原始索引。
然后在 .loc[...] 中使用,所以这是 boolean 的情况
索引。此列表的连续 True / False 元素与
来自 df_rts_1 的连续行并说明特定行是否
将 selected.
Q2 和 Q3。 any() 在这里做什么? any() 对我们有什么帮助
实现。
查看初始行的示例:
- 第一个条件(单独)说明是否 measurement_tstamp 在
当前 行 在 df_crsh_rts,
的连续行中的两个日期之间
- 第二个条件(单独)说明当前行是否有匹配
tmc 在 df_crsh_rts.
的连续行中
我们要求两个这些条件必须满足同一行
来自 df_crsh_rts,因此 & 加入了他们。
但请注意:
condition_1 & condition_2 产生 Series of bool 类型 - 是否
连续行满足两个部分条件:
0 True
1 False
2 False
Name: tmc, dtype: bool
但是我们不需要 bool 的任何 Series。我们需要一个 single bool,
说明上述结果是否包含至少一个 True 值。
还有这个转换(从 bool Series 到 single bool)
由 any().
执行
编辑 2
由于你的数据量很大,我想出了另一个,可能更快
解决方案。想法是:
- 组 df_rts_1 由 tmc_code,
- 只检查 between 条件
tmc.
- 为了加快 select 适当的间隔,使用辅助 Series
tmc 索引的间隔(按索引搜索更快)。
为此,定义以下函数,应用于每个组:
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)
最后 运行 崩溃 列的更新:
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 写下这两个解决方案的执行时间。
我有两个具有两种不同形状的数据框:
df_rts_1 #Shape: (38658637, 7)
df_crsh_rts #Shape: (9456, 6)
我正在尝试使用 np.where 来更新列值 (df_rts_1['crash'])根据一定条件等于1
如下:
df_rts_1['tmc_code']= df_crsh_rts['tmc']
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/data 科学还很陌生,因此非常感谢您的帮助。
假设你的两个 DataFrame 都包含:
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
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 的当前 行,让我们构建 您的情况:
- “介于”条件可以表示为
interv.contains(row.measurement_tstamp)
, - tmc / tmc_code值的等式可以表示为
df_crsh_rts.tmc.eq(row.tmc_code)
.
要检查它们是如何工作的,将 df_rts_1 的第一行保存为 行 变量:
row = df_rts_1.iloc[0]
并执行两个条件。
第一个条件生成一个 Numpy 数组 bool 类型:
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()
即以上两个条件的逻辑 AND 和 any() - 是否 any 这个连词的元素是 True.
与您的代码相比,最后的变化是:
- 而不是 where,使用 iloc[...] 其中第一个参数(行 selector) 是上面的复合条件,为每一行计算 来自 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
在评论中编辑以下问题
Q1。我们是否使用来自两个条件的索引来访问和更新 df_rts_1 数据框?
实际上不是。注意:
[ (interv.contains(row.measurement_tstamp) &
df_crsh_rts.tmc.eq(row.tmc_code)).any() for row in df_rts_1.itertuples() ]
产生一个 list of bools,它甚至不包含原始索引。 然后在 .loc[...] 中使用,所以这是 boolean 的情况 索引。此列表的连续 True / False 元素与 来自 df_rts_1 的连续行并说明特定行是否 将 selected.
Q2 和 Q3。 any() 在这里做什么? any() 对我们有什么帮助 实现。
查看初始行的示例:
- 第一个条件(单独)说明是否 measurement_tstamp 在 当前 行 在 df_crsh_rts, 的连续行中的两个日期之间
- 第二个条件(单独)说明当前行是否有匹配 tmc 在 df_crsh_rts. 的连续行中
我们要求两个这些条件必须满足同一行 来自 df_crsh_rts,因此 & 加入了他们。
但请注意:
condition_1 & condition_2 产生 Series of bool 类型 - 是否 连续行满足两个部分条件:
0 True 1 False 2 False Name: tmc, dtype: bool
但是我们不需要 bool 的任何 Series。我们需要一个 single bool, 说明上述结果是否包含至少一个 True 值。
还有这个转换(从 bool Series 到 single bool) 由 any().
执行编辑 2
由于你的数据量很大,我想出了另一个,可能更快 解决方案。想法是:
- 组 df_rts_1 由 tmc_code,
- 只检查 between 条件 tmc.
- 为了加快 select 适当的间隔,使用辅助 Series tmc 索引的间隔(按索引搜索更快)。
为此,定义以下函数,应用于每个组:
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)
最后 运行 崩溃 列的更新:
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 写下这两个解决方案的执行时间。