为什么此代码在一种情况下却无法在另一种情况下工作?

时间:2019-08-21 12:21:01

标签: python pandas

我正在is_holiday列中手动填充一些分类标签。有些行只有第一个观察结果带有正确的标签,其余的为0,我将这些零填满:

# Before filling
print(main_data.loc["25 December, 2012"].is_holiday)

date_time
2012-12-25 00:00:00    3
2012-12-25 01:00:00    0
2012-12-25 02:00:00    0
2012-12-25 03:00:00    0
.
.
.
2012-12-25 19:00:00    0
2012-12-25 20:00:00    0
2012-12-25 21:00:00    0
2012-12-25 22:00:00    0
2012-12-25 23:00:00    0
Name: is_holiday, dtype: int64

# Manually fill
for row in range(len(main_data.loc["2012"])):
    if main_data.Month[row] == 12 and main_data.Day[row] == 25:
        if main_data.is_holiday[row] == 0:
            main_data.is_holiday[row] = 3  # 3 is label for Xmas

# After filling
print(main_data.loc["25 December, 2012"].is_holiday)
2012-12-25 00:00:00    3
2012-12-25 01:00:00    3
2012-12-25 02:00:00    3
2012-12-25 03:00:00    3
.
.
.
2012-12-25 19:00:00    3
2012-12-25 20:00:00    3
2012-12-25 21:00:00    3
2012-12-25 22:00:00    3
2012-12-25 23:00:00    3
Name: is_holiday, dtype: int64

但是,如果我将同一代码再执行一年(例如2013年),则值将保持不变。我尝试修改代码,包括较小的更改,但假日标签不会更改:

# Before filling
print(main_data.loc["25 December, 2013"].is_holiday)

date_time
2013-12-25 00:00:00    3
2013-12-25 01:00:00    0
2013-12-25 02:00:00    0
2013-12-25 03:00:00    0
.
.
.
2013-12-25 19:00:00    0
2013-12-25 20:00:00    0
2013-12-25 21:00:00    0
2013-12-25 22:00:00    0
2013-12-25 23:00:00    0
Name: is_holiday, dtype: int64

# Manually fill
for row_2 in range(len(main_data.loc["2013"])):
    if main_data.Month[row_2] == 12 and main_data.Day[row_2] == 25:
        if main_data.is_holiday[row_2] == 0:
            main_data.is_holiday[row_2] = 3  # 3 is label for Xmas

# After filling
print(main_data.loc["25 December, 2013"].is_holiday)
2013-12-25 00:00:00    3
2013-12-25 01:00:00    0
2013-12-25 02:00:00    0
2013-12-25 03:00:00    0
.
.
.
2013-12-25 19:00:00    0
2013-12-25 20:00:00    0
2013-12-25 21:00:00    0
2013-12-25 22:00:00    0
2013-12-25 23:00:00    0
Name: is_holiday, dtype: int64

我在这里想念什么?我没想到会发生这种情况。对于某些假期,它可以正常工作,而对于其他假期,则不会。 请记住,MonthDay是我在main_data中设计的单独列。

编辑:欢迎使用更好的方法来实现这一目标。

4 个答案:

答案 0 :(得分:2)

Pandas具有一些不错的内置函数来完成此类任务。所以你可以做

import numpy as np
main_data.is_holiday.replace(0, np.nan, inplace=True)
main_data.is_holiday.fillna(method='ffill', inplace=True)

应该这样做。

编辑:

仅将填充应用于假期:

main_data['is_holiday'] = main_data.is_holiday.resample('D').max()
main_data.is_holiday.fillna(method='ffill', inplace=True)

第一行将is_holiday列替换为假定存在的午夜时间戳记的当天最大值。第二行填充其他行,现在应该有一个NaN。

答案 1 :(得分:2)

假设日期是我只想做的索引:

df.loc[(df.index.day == 25) & (df.index.month ==12),['is_holiday']] = 3

带有示例的完整代码:

#init data
df = pd.DataFrame(          \    
[['2012-12-25 19:00:00',0,0], \
['2012-12-25 20:00:00',0,0],  \
['2012-12-26 19:00:00',0,0],  \
['2012-12-26 20:00:00',0,0],  \
['2013-01-25 19:00:00',0,0],  \
['2013-01-25 20:00:00',0,0],  \
['2013-12-25 19:00:00',0,0],  \
['2013-12-25 20:00:00',0,0]])

#set index
df.columns = ['date','is_holiday','some_value']
df['date'] = pd.to_datetime(df['date'])
df = df.set_index('date')

#do the search
df.loc[(df.index.day == 25) & (df.index.month ==12),['is_holiday']] = 3
print(df)

结果:

                     is_holiday  value
date                                  
2012-12-25 19:00:00  3           0    
2012-12-25 20:00:00  3           0    
2012-12-26 19:00:00  0           0    
2012-12-26 20:00:00  0           0    
2013-01-25 19:00:00  0           0    
2013-01-25 20:00:00  0           0    
2013-12-25 19:00:00  3           0    
2013-12-25 20:00:00  3           0 

一些有用的链接:

https://pandas.pydata.org/pandas-docs/stable/user_guide/timeseries.html#time-date-components

https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.loc.html

Select rows from a DataFrame based on values in a column in pandas

答案 2 :(得分:1)

您实际上在做什么

for row in range(len(main_data.loc["2012"]))
#let's says len(main_data.loc["2012"]) = 100

您选择第0到100行,并将0替换为3。

for row_2 in range(len(main_data.loc["2013"]))
#let's says len(main_data.loc["2013"]) = 50

您选择第0到50行,并将0替换为3。

您正在主数据集中执行此操作,因此这两个代码都将替换数据集的第一行。

您可以使用(伪代码)之类的方法解决该问题:

for row in np.where(years=2013,month==12)

答案 3 :(得分:1)

正如我在评论中建议的那样,您可以使用DataFrame.where或np.where进行分配,但是我认为您的情况中最好的是DataFrame.where:

mask = (main_data.date_time.dt.year == 2012) & (main_data.Month == 12) & (main_data.Day == 25)
main_data[mask].is_holiday = main_data[mask]\
                                    .is_holiday\
                                    .where(~(main_data[mask].is_holiday == 0)), 3)
  1. numpy.where
main_data[mask].is_holiday = np.where(main_data[mask].is_holiday == 0, 3,\
                                             main_data[mask].is_holiday)