根据条件更新 groupby 对象上的 df 列值
Update df column values on groupby object based on condition
我无法找到一种有效的方法来更新大型 pandas DataFrame 中的某些列值。
下面的代码创建了一个与我正在使用的格式类似的 DataFrame。数据摘要:DataFrame 包含三天的消耗数据,每天分为 10 个测量周期。每个测量周期也记录在四个独立的过程中,即初步读数、日终读数和两个后来的修订,所有更新都记录在 Last_Update 列和日期。
dates = ['2022-01-01']*40 + ['2022-01-02']*40 + ['2022-01-03']*40
periods = list(range(1,11))*12
versions = (['PRELIM'] * 10 + ['DAILY'] * 10 + ['REVISE'] * 20) * 3
data = {'Date': dates,
'Period' : periods,
'Version': versions,
'Consumption': np.random.randint(1, 30, 120)}
df = pd.DataFrame(data)
df.Date = pd.to_datetime(df.Date)
## Add random times to the REVISE Last_Update values
df['Last_Update'] = df['Date'].apply(lambda x: x + pd.Timedelta(hours=np.random.randint(1,23), minutes=np.random.randint(1,59)))
df['Last_Update'] = df['Last_Update'].where(df.Version == 'REVISE', df['Date'])
问题是两个修订类别都由相同的值指定:“REVISE”。其中一个“REVISE”值必须更改为类似“REVISE_2”的值。如果您按以下方式对数据进行分组 df.groupby(['Date', 'Period', 'Version', 'Last_Update'])['Consumption'].sum()
,您可以看到每天的每个期间有两个 Last_Update 日期用于 REVISE。所以我们需要将日期最大的REVISE设置为REVISE_2.
我设法找到解决方案的唯一方法是使用一个非常复杂的函数和 apply 方法来测试哪个日期更大并存储其索引,然后使用 loc 更改值。这最终导致小部分数据花费了大量时间(完整的数据集有数百万行)。
我觉得有一个使用 groupby 函数的简单解决方案,因为我在导航多索引输出时遇到困难。
如有任何帮助,我们将不胜感激。
我们在一些分组后使用 idxmax
计算最大修订日期的索引,然后更改标签:
last_revised_date_idx = df[df['Version'] == 'REVISE'].groupby(['Date', 'Period'], group_keys = False)['Last_Update'].idxmax()
df.loc[last_revised_date_idx, 'Version'] = 'REVISE_2'
检查输出:
df.groupby(['Date', 'Period', 'Version', 'Last_Update'])['Consumption'].count().head(20)
产生
Date Period Version Last_Update
2022-01-01 1 DAILY 2022-01-01 00:00:00 1
PRELIM 2022-01-01 00:00:00 1
REVISE 2022-01-01 03:50:00 1
REVISE_2 2022-01-01 12:10:00 1
2 DAILY 2022-01-01 00:00:00 1
PRELIM 2022-01-01 00:00:00 1
REVISE 2022-01-01 10:45:00 1
REVISE_2 2022-01-01 22:05:00 1
3 DAILY 2022-01-01 00:00:00 1
PRELIM 2022-01-01 00:00:00 1
REVISE 2022-01-01 17:03:00 1
REVISE_2 2022-01-01 19:10:00 1
4 DAILY 2022-01-01 00:00:00 1
PRELIM 2022-01-01 00:00:00 1
REVISE 2022-01-01 15:23:00 1
REVISE_2 2022-01-01 18:08:00 1
5 DAILY 2022-01-01 00:00:00 1
PRELIM 2022-01-01 00:00:00 1
REVISE 2022-01-01 12:19:00 1
REVISE_2 2022-01-01 18:04:00 1
我无法找到一种有效的方法来更新大型 pandas DataFrame 中的某些列值。
下面的代码创建了一个与我正在使用的格式类似的 DataFrame。数据摘要:DataFrame 包含三天的消耗数据,每天分为 10 个测量周期。每个测量周期也记录在四个独立的过程中,即初步读数、日终读数和两个后来的修订,所有更新都记录在 Last_Update 列和日期。
dates = ['2022-01-01']*40 + ['2022-01-02']*40 + ['2022-01-03']*40
periods = list(range(1,11))*12
versions = (['PRELIM'] * 10 + ['DAILY'] * 10 + ['REVISE'] * 20) * 3
data = {'Date': dates,
'Period' : periods,
'Version': versions,
'Consumption': np.random.randint(1, 30, 120)}
df = pd.DataFrame(data)
df.Date = pd.to_datetime(df.Date)
## Add random times to the REVISE Last_Update values
df['Last_Update'] = df['Date'].apply(lambda x: x + pd.Timedelta(hours=np.random.randint(1,23), minutes=np.random.randint(1,59)))
df['Last_Update'] = df['Last_Update'].where(df.Version == 'REVISE', df['Date'])
问题是两个修订类别都由相同的值指定:“REVISE”。其中一个“REVISE”值必须更改为类似“REVISE_2”的值。如果您按以下方式对数据进行分组 df.groupby(['Date', 'Period', 'Version', 'Last_Update'])['Consumption'].sum()
,您可以看到每天的每个期间有两个 Last_Update 日期用于 REVISE。所以我们需要将日期最大的REVISE设置为REVISE_2.
我设法找到解决方案的唯一方法是使用一个非常复杂的函数和 apply 方法来测试哪个日期更大并存储其索引,然后使用 loc 更改值。这最终导致小部分数据花费了大量时间(完整的数据集有数百万行)。
我觉得有一个使用 groupby 函数的简单解决方案,因为我在导航多索引输出时遇到困难。
如有任何帮助,我们将不胜感激。
我们在一些分组后使用 idxmax
计算最大修订日期的索引,然后更改标签:
last_revised_date_idx = df[df['Version'] == 'REVISE'].groupby(['Date', 'Period'], group_keys = False)['Last_Update'].idxmax()
df.loc[last_revised_date_idx, 'Version'] = 'REVISE_2'
检查输出:
df.groupby(['Date', 'Period', 'Version', 'Last_Update'])['Consumption'].count().head(20)
产生
Date Period Version Last_Update
2022-01-01 1 DAILY 2022-01-01 00:00:00 1
PRELIM 2022-01-01 00:00:00 1
REVISE 2022-01-01 03:50:00 1
REVISE_2 2022-01-01 12:10:00 1
2 DAILY 2022-01-01 00:00:00 1
PRELIM 2022-01-01 00:00:00 1
REVISE 2022-01-01 10:45:00 1
REVISE_2 2022-01-01 22:05:00 1
3 DAILY 2022-01-01 00:00:00 1
PRELIM 2022-01-01 00:00:00 1
REVISE 2022-01-01 17:03:00 1
REVISE_2 2022-01-01 19:10:00 1
4 DAILY 2022-01-01 00:00:00 1
PRELIM 2022-01-01 00:00:00 1
REVISE 2022-01-01 15:23:00 1
REVISE_2 2022-01-01 18:08:00 1
5 DAILY 2022-01-01 00:00:00 1
PRELIM 2022-01-01 00:00:00 1
REVISE 2022-01-01 12:19:00 1
REVISE_2 2022-01-01 18:04:00 1