我有一个包含月份和年份列的数据框。两者都包含字符串,即“ September”和“ 2013”。如何选择2013年9月至2008年5月之间的所有行?
df1 = stats_month_census_2[(stats_month_census_2['year'] <= '2013')
& (stats_month_census_2['year'] >= '2008')]
df2 = df1[...]
在上面的代码之后,我打算再次做同样的事情,但是我很难拿出聪明的代码来简单地删除时间比2013年9月(“十月至十二月”)高的行。并且在2008年5月以下。我可以轻松地对此进行硬编码,但是必须有一种更Python的方式来实现此目的...
答案 0 :(得分:3)
您可以使用pd.to_datetime
轻松地将列转换为DateTime列>>df
month year
0 January 2000
1 April 2001
2 July 2002
3 February 2010
4 February 2018
5 March 2014
6 June 2012
7 June 2011
8 May 2009
9 November 2016
>>df['date'] = pd.to_datetime(df['month'].astype(str) + '-' + df['year'].astype(str), format='%B-%Y')
>>df
month year date
0 January 2000 2000-01-01
1 April 2001 2001-04-01
2 July 2002 2002-07-01
3 February 2010 2010-02-01
4 February 2018 2018-02-01
5 March 2014 2014-03-01
6 June 2012 2012-06-01
7 June 2011 2011-06-01
8 May 2009 2009-05-01
9 November 2016 2016-11-01
>>df[(df.date <= "2013-09") & (df.date >= "2008-05") ]
month year date
3 February 2010 2010-02-01
6 June 2012 2012-06-01
7 June 2011 2011-06-01
8 May 2009 2009-05-01
答案 1 :(得分:3)
或者,您可以按照帖子“选择2013年9月至2008年5月之间的所有行” 中的说明,尝试查找2008年至2013年之间的行数。 然后使用pandas.Series.between:
从@jezrael借用的数据集。
用于演示目的的数据框:
>>> stats_month_census_2
year month data
0 2008 April 1
1 2008 May 3
2 2008 June 4
3 2013 September 6
4 2013 October 5
5 2014 November 6
6 2014 December 7
使用pandas.Series.between()
>>> stats_month_census_2[stats_month_census_2['year'].between(2008, 2013, inclusive=True)]
year month data
0 2008 April 1
1 2008 May 3
2 2008 June 4
3 2013 September 6
4 2013 October 5
如果只是datetime
格式的问题,您可以尝试以下操作:
>>> stats_month_census_2[stats_month_census_2['year'].between('2008-05', '2013-09', inclusive=True)]
year month data
1 2008-05-01 May 3
2 2008-06-01 June 4
3 2013-09-01 September 6
使用DataFame.query:
>>> stats_month_census_2.query('"2008-05" <= year <= "2013-09"')
year month data
1 2008-05-01 May 3
2 2008-06-01 June 4
3 2013-09-01 September 6
使用isin方法:选择两个日期之间的行
>>> stats_month_census_2[stats_month_census_2['year'].isin(pd.date_range('2008-05-01', '2013-09-01'))]
year month data
1 2008-05-01 May 3
2 2008-06-01 June 4
3 2013-09-01 September 6
或者,甚至您也可以像下面那样通过。
>>> stats_month_census_2[stats_month_census_2['year'].isin(pd.date_range('2008-05', '2013-09'))]
year month data
1 2008-05-01 May 3
2 2008-06-01 June 4
3 2013-09-01 September 6
使用 loc
方法,具体方法是根据索引的开始和结束日期进行划分。
Start = stats_month_census_2[stats_month_census_2['year'] =='2008-05'].index[0]
End = stats_month_census_2[stats_month_census_2['year']=='2013-09'].index[0]
>>> stats_month_census_2.loc[Start:End]
year month data
1 2008-05-01 May 3
2 2008-06-01 June 4
3 2013-09-01 September 6
注意:出于好奇,正如@jezrael在评论中要求的那样,我要添加如何将year
列转换为日期时间格式:
因为我们有下面的示例DataFrame,其中有两个不同的列year
和month
,其中year列只有Years,month列是文字字符串格式,所以,首先我们需要转换String转换为int形式,或通过使用pd.to_datetime
方法为所有熊猫分配一天作为1,将年或月加起来或加在一起。
df
year month data
0 2008 April 1
1 2008 May 3
2 2008 June 4
3 2013 September 6
4 2013 October 5
5 2014 November 6
6 2014 December 7
上面是日期时间转换之前的原始DataFrame。所以,我采用以下方法,这是我随时间在vi SO本身中学到的。
1-首先,将month
名称转换为int形式,然后轻松地将其分配到名为Month
的新列中。因此,我们以后可以将其用于转换。
df['Month'] = pd.to_datetime(df.month, format='%B').dt.month
2-其次,或者最后直接通过将datetime
列本身直接分配,将year列直接转换为适当的year
格式,这是我们可以说的一种地方。
df['Date'] = pd.to_datetime(df[['year', 'Month']].assign(Day=1))
现在,所需的DataFrame和
year
列为日期时间格式:
print(df)
year month data Month
0 2008-04-01 April 1 4
1 2008-05-01 May 3 5
2 2008-06-01 June 4 6
3 2013-09-01 September 6 9
4 2013-10-01 October 5 10
5 2014-11-01 November 6 11
6 2014-12-01 December 7 12
答案 2 :(得分:2)
您可以创建DatetimeIndex
,然后按partial string indexing
进行选择:
stats_month_census_2 = pd.DataFrame({
'year': [2008, 2008, 2008, 2013,2013],
'month': ['April','May','June','September','October'],
'data':[1,3,4,6,5]
})
print (stats_month_census_2)
year month data
0 2008 April 1
1 2008 May 3
2 2008 June 4
3 2013 September 6
4 2013 October 5
s = stats_month_census_2.pop('year').astype(str) + stats_month_census_2.pop('month')
#if need year and month columns
#s = stats_month_census_2['year'].astype(str) + stats_month_census_2['month']
stats_month_census_2.index = pd.to_datetime(s, format='%Y%B')
print (stats_month_census_2)
data
2008-04-01 1
2008-05-01 3
2008-06-01 4
2013-09-01 6
2013-10-01 5
print (stats_month_census_2['2008':'2013'])
data
2008-04-01 1
2008-05-01 3
2008-06-01 4
2013-09-01 6
2013-10-01 5
print (stats_month_census_2['2008-05':'2013-09'])
data
2008-05-01 3
2008-06-01 4
2013-09-01 6
或创建列并将between
与boolean indexing
结合使用:
s = stats_month_census_2['year'].astype(str) + stats_month_census_2['month']
stats_month_census_2['date'] = pd.to_datetime(s, format='%Y%B')
print (stats_month_census_2)
year month data date
0 2008 April 1 2008-04-01
1 2008 May 3 2008-05-01
2 2008 June 4 2008-06-01
3 2013 September 6 2013-09-01
4 2013 October 5 2013-10-01
df = stats_month_census_2[stats_month_census_2['date'].between('2008-05', '2013-09')]
print (df)
year month data date
1 2008 May 3 2008-05-01
2 2008 June 4 2008-06-01
3 2013 September 6 2013-09-01
不幸的是,在某些年份之前,无法通过datetime列使用这种方式,因此需要在pygo
列中使用year
解决方案:
#wrong output
df = stats_month_census_2[stats_month_census_2['date'].between('2008', '2013')]
print (df)
year month data date
0 2008 April 1 2008-04-01
1 2008 May 3 2008-05-01
2 2008 June 4 2008-06-01
答案 3 :(得分:2)
另一种解决方案:
让我们假设df如下图所示:
series name Month Year
0 fertility rate May 2008
1 CO2 emissions June 2009
2 fertility rate September 2013
3 fertility rate October 2013
4 CO2 emissions December 2014
创建日历字典映射并保存在新列中
import calendar
d = dict((v,k) for k,v in enumerate(calendar.month_abbr))
stats_month_census_2['month_int'] = stats_month_census_2.Month.apply(lambda x: x[:3]).map(d)
>>stats_month_census_2
series name Month Year month_int
0 fertility rate May 2008 5
1 CO2 emissions June 2009 6
2 fertility rate September 2013 9
3 fertility rate October 2013 10
4 CO2 emissions December 2014 12
使用进行过滤 series.between()
stats_month_census_2[stats_month_census_2.month_int.between(5,9,inclusive=True) & stats_month_census_2.Year.between(2008,2013,inclusive=True)]
输出:
series name Month Year month_int
0 fertility rate May 2008 5
1 CO2 emissions June 2009 6
2 fertility rate September 2013 9