Как выполнить упорядоченный выбор нескольких столбцов по значению - PullRequest
0 голосов
/ 06 января 2019

У меня есть датафрейм, включающий столбец месяца и года. Оба содержат строки, то есть «сентябрь» и «2013». Как выбрать все строки в период с сентября 2013 года по май 2008 года в одной строке?

df1 = stats_month_census_2[(stats_month_census_2['year'] <= '2013')
                 & (stats_month_census_2['year'] >= '2008')]

df2 = df1[...]

После кода выше я собирался сделать то же самое снова, но мне трудно придумать умный код, чтобы просто избавиться от строк, которые выше по времени, чем сентябрь 2013 года (с октября по декабрь) и ниже мая 2008 года. Я мог бы легко написать это жестко, но должен быть более питонский способ сделать это ...

Ответы [ 4 ]

0 голосов
/ 06 января 2019

Другое решение:

Предположим, что 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
0 голосов
/ 06 января 2019

Вы можете легко преобразовать столбцы в столбец DateTime, используя pd.to_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
0 голосов
/ 06 января 2019

Или вы можете попробовать ниже, если вы ищете падение строк между 2008 и 2013 годами, как вы просили в посте "выбрать все строки в период с сентября 2013 года по май 2008 года" затем используйте pandas.Series.between :

Набор данных заимствован у @jezrael ..

DataFrame для демонстрационных целей:

>>> 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 содержит только годы, а столбец month представлен в формате буквенной строки. Итак, сначала нам нужно преобразовать String в форму int присоединитесь или добавьте год и месяц вместе, назначив день 1 для всех, используя метод панд pd.to_datetime.

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 до преобразования даты и времени. Итак, я использую нижеприведенный подход, который я выучил за это время непосредственно в SO.

1- Сначала преобразуйте имена month в форму int и назначьте их для нового столбца с именем Month, так что мы можем использовать его для преобразования позже.

df['Month'] = pd.to_datetime(df.month, format='%B').dt.month

2- Во-вторых, или, наконец, преобразуйте непосредственно столбец года в правильный формат datetime, непосредственно назначив самому столбцу year это своего рода место, которое мы можем сказать.

df['Date'] = pd.to_datetime(df[['year', 'Month']].assign(Day=1))

Теперь столбец Desired DataFrame и year находится в форме datetime:

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
0 голосов
/ 06 января 2019

Вы можете создать 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

К сожалению, этот способ со столбцом даты и времени невозможен для выбранных лет, поэтому необходимо решение 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...