如何更改df1的列值相对于df2选定行中的单个值?



我有一个如下所示的df1df1中的行是使用df2的开始和结束日期选择的。如您所见,CaseNamedf2具有关联的 ID 号。

问题: 我想更新/更改/替换df1中的CaseName(由屏蔽日期时间戳w.r.t选择。df2)CaseNamedf2.

df的原始形状是 (80000,15) 其余列是属性值。 使用开始和结束日期选择后

df1.shape = (29467,15)
Index CaseName TStamp
0     CASE_A   2016-05-19 00:00
1     CASE_A   2016-05-19 01:00
2     CASE_A   2016-05-19 02:00
3     CASE_A   2016-05-19 03:00
4     CASE_A   2016-05-19 04:00
5     CASE_B   2016-07-30 00:00
6     CASE_B   2016-07-30 02:00
7     CASE_B   2016-07-30 03:00
8     CASE_B   2016-07-30 04:00
9     CASE_B   2016-07-30 05:00
10    CASE_B   2016-07-30 06:00
df2.shape = (23,3)
Index CaseName    Start      End
0     CASE_A1     2016-05-19 2016-08-30
1     CASE_A2     2016-08-30 2017-01-06
2     CASE_A3     2017-01-06 2017-05-08
3     CASE_A4     2017-05-08 2017-08-01
4     CASE_A5     2017-08-01 2018-06-24
5     CASE_B1     2016-05-20 2016-07-30
6     CASE_B2     2016-07-30 2016-10-16
7     CASE_B3     2016-10-16 2017-01-14
8     CASE_B4     2017-01-14 2017-05-08
9     CASE_B5     2017-05-08 2017-08-03
10    CASE_B6     2017-08-03 2018-06-25

我试过了

  • df2中逐行迭代。
  • 使用df2.Startdf2.End创建蒙版。
  • 应用条件来分配值。
  • 实际上df1有多种情况CASE_A,B,C,D。
#For single condition CASE_A
for index,row in df2.iterrows():
mask = (df1['TStamp'] > row['Start']) & (df1['TStamp'] <= row['End'])
temp_df = df1.loc[mask]
temp_df.loc[temp_df['CaseName'] == 'CASE_A','CaseName'] = row['CaseName ']

预期输出如下所示:

result_df1.shape = (29467,15)
Index CaseName TStamp
0     CASE_A1   2016-05-19 00:00
1     CASE_A1   2016-05-19 01:00
2     CASE_A1   2016-05-19 02:00
3     CASE_A1   2016-05-19 03:00
4     CASE_A1   2016-05-19 04:00
5     CASE_B2   2016-07-30 00:00
6     CASE_B2   2016-07-30 02:00
7     CASE_B2   2016-07-30 03:00
8     CASE_B2   2016-07-30 04:00
9     CASE_B2   2016-07-30 05:00
10    CASE_B2   2016-07-30 06:00

使用:

#convert columns to datetimes
df1['TStamp'] = pd.to_datetime(df1['TStamp'])
df2['Start'] = pd.to_datetime(df2['Start'])
df2['End'] = pd.to_datetime(df2['End'])
#remove last value in strings
df2['CaseName'] = df2['CaseName'].str[:-1]
#merge together
df = df1.merge(df2, on='CaseName')
#filter by condition and by columns names
mask = (df['TStamp'] > df['Start']) & (df['TStamp'] <= df['End'])
df = df.loc[mask, df1.columns]
print (df)
CaseName              TStamp
5    CASE_A 2016-05-19 01:00:00
10   CASE_A 2016-05-19 02:00:00
15   CASE_A 2016-05-19 03:00:00
20   CASE_A 2016-05-19 04:00:00
25   CASE_B 2016-07-30 00:00:00
32   CASE_B 2016-07-30 02:00:00
38   CASE_B 2016-07-30 03:00:00
44   CASE_B 2016-07-30 04:00:00
50   CASE_B 2016-07-30 05:00:00
56   CASE_B 2016-07-30 06:00:00

假设所有日期列都已转换为日期时间。以下方法使用between检查值是否属于某个范围

(df2.assign(CaseName1=df2.CaseName.str[:-1])
.join(df1.set_index('CaseName'), on='CaseName1')
.loc[lambda x:x.TStamp.between(x.Start,x.End),['CaseName','TStamp']])

最新更新