Pandas:如何删除包含无效月/日列组合的行,例如2月30日?

时间:2018-03-01 22:28:50

标签: python pandas

我的源数据使用31列作为日期值,每个月有一行。我将31天的列熔化为单日列,现在我想将年,月和日列合并到日期时间(?)列中,以便按行/月/日对行进行排序。

融化后,我的数据框看起来像这样:

       year  month day   prcp
0      1893      1  01    0.0
1      1893      2  01    0.0
2      1893      3  01    0.0
3      1893      4  01    NaN
4      1893      5  01    NaN
5      1893      6  01    NaN
6      1893      7  01    NaN
7      1893      8  01    0.0
8      1893      9  01   10.0
9      1893     10  01    0.0
10     1893     11  01    0.0
11     1893     12  01    NaN
12     1894      1  01    NaN
13     1894      2  01    0.0
14     1894      3  01    NaN
...

接下来我试图创造一个时间'我可以排序的列,使用year,month和day列作为datetime构造函数的参数。我尝试过这种做法:

def make_datetime(y, m, d):
    return(datetime(year=y, month=m, day=d))

df['time'] = np.vectorize(make_datetime)(df['year'].astype(int), df['month'].astype(int), df['day'].astype(int))

上述并不能让我在那里,因为在月/日专栏没有合理意义的情况下会失败,例如2月29日非闰年,4月31日等。我想我接下来想要做的是以某种方式将datetime()调用包装在try / catch中,当由于不兼容的月/日组合而导致时,我应该将该行放在catch块中。如果不对所有行执行for循环,我将如何去做?还是有更好的方法来破解这个坚果?

提前感谢任何建议或见解。

2 个答案:

答案 0 :(得分:3)

这是使用您在try / except条款中换行的建议的一种方式。

from datetime import datetime

def dater(x):
    try:
        return datetime(year=x['year'], month=x['month'], day=x['day'])
    except ValueError:
        return None

df['date'] = df.apply(dater, axis=1)

#    year  month  day       date
# 0  1890      2   29        NaT
# 1  1891      2   29        NaT
# 2  1892      2   29 1892-02-29
# 3  1893      2   29        NaT
# 4  1894      2   29        NaT
# 5  1895      2   29        NaT
# 6  1896      2   29 1896-02-29
# 7  1897      2   29        NaT
# 8  1898      2   29        NaT

df = df.dropna(subset=['date'])

#    year  month  day       date
# 2  1892      2   29 1892-02-29
# 6  1896      2   29 1896-02-29

答案 1 :(得分:3)

你可以将你的df强制传递给to_datetime

pd.to_datetime(df,errors='coerce')
Out[905]: 
#          NaT
#          NaT
#   1892-02-29
#          NaT
#          NaT
#          NaT
#   1896-02-29
#          NaT
#          NaT
dtype: datetime64[ns]
df['New']=pd.to_datetime(df,errors='coerce')
df.dropna()
Out[907]: 
   year  month  day        New
#  1892      2   29 1892-02-29
#  1896      2   29 1896-02-29