Как заполнить пустые ячейки в df на основе строки в последовательной строке, Pandas - PullRequest
5 голосов
/ 08 июля 2020

У меня есть df, где данные выглядят так:

  Time      Value
            60.8
  Jul 2019  58.1
            58.8
            56.9
  Oct 2019  51.8
            54.6
            56.8
  Jan 2020  58.8
            54.2
            51.3
  Apr 2020  52.2

Я хочу заполнить пустые ячейки в переменной Time в соответствии с календарным годом. Итак:

  Time      Value
  Jun 2019  60.8
  Jul 2019  58.1
  Aug 2019  58.8
  Sep 2019  56.9
  Oct 2019  51.8
  Nov 2019  54.6
  Dec 2019  56.8
  Jan 2020  58.8
  Feb 2020  54.2
  Mar 2020  51.3
  Apr 2020  52.2

Я видел сообщение, в котором pandas можно использовать для заполнения numeri c values ​​, но поскольку моя переменная не обязательно определяется в numeri c Кстати, я не совсем уверен, как применить это в этой ситуации.

Мне кажется, есть два способа приблизиться к этому: 1) изменить список перед записью в df. 2) Изменение df.

Я предпочитаю первое решение, но не уверен, возможно ли это.

Спасибо.

Мой сценарий:

totalmonth=['', 'Jul 2019', '', '', 'Oct 2019', '', '', 'Jan 2020', '', '', 'Apr 2020', '']
totalvalue=['60.8', '58.1', '58.8', '56.9', '51.8', '54.6', '56.8', '58.8', '54.2', '51.3', '52.2', '48.7']

df = pd.DataFrame({'Time': totalmonth,
                   'Value': totalvalue})

Ответы [ 3 ]

1 голос
/ 11 июля 2020

Минимальный минус 1 в столбце «Время» - это месяц начала, максимальный плюс 2 в столбце «Время» - последний месяц, а целевой столбец обновляется на date_range() для получения последовательных значений.

df['Time'] = pd.to_datetime(df['Time'])
startM = datetime.datetime((df['Time'].min()).year,(df['Time'].min()).month-1,1)
endM = datetime.datetime((df['Time'].max()).year,(df['Time'].max()).month+2,1)
df['Time'] = pd.date_range(startM,endM, freq='1M')
df
    Time    Value
0   2019-06-30  60.8
1   2019-07-31  58.1
2   2019-08-31  58.8
3   2019-09-30  56.9
4   2019-10-31  51.8
5   2019-11-30  54.6
6   2019-12-31  56.8
7   2020-01-31  58.8
8   2020-02-29  54.2
9   2020-03-31  51.3
10  2020-04-30  52.2
11  2020-05-31  48.7
1 голос
/ 11 июля 2020

Сначала используйте pd.to_datetime, чтобы преобразовать столбец Time в pandas ряд даты и времени t, затем используйте pd.period_range, чтобы сгенерировать диапазон периодов с ежемесячным частота и начальный период равны расчетному периоду и количеству периодов, равному length серии t, наконец, используйте .strftime со спецификатором формата %b %Y, чтобы вернуть строковое представление из period_range в желаемом формате:

t = pd.to_datetime(df['Time'])
df['Time'] = pd.period_range(
    t.min().to_period('M') - t.idxmin(), periods=len(t), freq='M').strftime('%b %Y')

Детали:

# print(t)
0           NaT
1    2019-07-01
2           NaT
3           NaT
4    2019-10-01
5           NaT
6           NaT
7    2020-01-01
8           NaT
9           NaT
10   2020-04-01
11          NaT
Name: Time, dtype: datetime64[ns]

# print(t.min(), t.idxmin())
Timestamp('2019-07-01 00:00:00'), 1

# print(t.min().to_period('M') - t.idxmin())
Period('2019-06', 'M') # starting period of the period range

Результат:

# print(df)

        Time Value
0   Jun 2019  60.8
1   Jul 2019  58.1
2   Aug 2019  58.8
3   Sep 2019  56.9
4   Oct 2019  51.8
5   Nov 2019  54.6
6   Dec 2019  56.8
7   Jan 2020  58.8
8   Feb 2020  54.2
9   Mar 2020  51.3
10  Apr 2020  52.2
11  May 2020  48.7
1 голос
/ 11 июля 2020

Хорошо, это заняло у меня больше времени, чем я хотел бы признать. Я решил для вашего первого ответа

Вывод:

***********************BEFORE********************************

['', 'Jul 2019', '', '', 'Oct 2019', '', '', 'Jan 2020', '', '', 'Apr 2020', '']
        Time Value
0             60.8
1   Jul 2019  58.1
2             58.8
3             56.9
4   Oct 2019  51.8
5             54.6
6             56.8
7   Jan 2020  58.8
8             54.2
9             51.3
10  Apr 2020  52.2
11            48.7

***********************AFTER********************************

['Jun 2019', 'Jul 2019', 'Aug 2019', 'Sep 2019', 'Oct 2019', 'Nov 2019', 'Dec 2019', 'Jan 2020', 'Feb 2020', 'Mar 2020', 'Apr 2020', 'May 2020']
        Time Value
0   Jun 2019  60.8
1   Jul 2019  58.1
2   Aug 2019  58.8
3   Sep 2019  56.9
4   Oct 2019  51.8
5   Nov 2019  54.6
6   Dec 2019  56.8
7   Jan 2020  58.8
8   Feb 2020  54.2
9   Mar 2020  51.3
10  Apr 2020  52.2
11  May 2020  48.7

Код:

from datetime import datetime
from dateutil.relativedelta import relativedelta
totalmonth=['', 'Jul 2019', '', '', 'Oct 2019', '', '', 'Jan 2020', '', '', 'Apr 2020', '']

new_totalmonth = [datetime.strptime(x,'%b %Y') for x in totalmonth if x != '' ]
index = totalmonth.index(min(new_totalmonth).strftime('%b %Y'))
new_totalmonth = [(min(new_totalmonth) + relativedelta(months=x)).strftime('%b %Y') for x in range(-index,len(totalmonth) - index)]
print(new_totalmonth)

Разбивка

Эта строка код создает список всех допустимых дат и помещает их в формат, в котором я могу запустить функцию min ().

new_totalmonth = [datetime.strptime(x,'%b %Y') for x in totalmonth if x != '' ]

Что это выводит

print(new_totalmonth)

[datetime.datetime(2019, 7, 1, 0, 0), datetime.datetime(2019, 10, 1, 0, 0), datetime.datetime(2020, 1, 1, 0, 0), datetime.datetime(2020, 4, 1, 0, 0)]

Это создает индекс переменной и присваивает ему индекс минимальной даты в общем месяце

index = totalmonth.index(min(new_totalmonth).strftime('%b %Y'))

min(new_totalmonth)  # this is finding the minimum date in new_totalmonth
print(min(new_totalmonth))

2019-07-01 00:00:00
min(new_totalmonth).strftime('%b %Y')  # This is putting that minimum in a format that matches what is in totalmonth so the function totalmonth.index() can get the correct index

print(min(new_totalmonth).strftime('%b %Y'))

Jul 2019

Используется понимание списка.

new_totalmonth = [(min(new_totalmonth) + relativedelta(months=x)).strftime('%b %Y') for x in range(-index,len(totalmonth) - index)]

Я использую индекс минимальной даты в totalmonth, чтобы управлять диапазоном значений (сколько месяцев), которые я собираюсь добавить к минимальному месяцу в totalmonth

range(-index,len(totalmonth) - index)

print(list(range(-index,len(totalmonth) - index)))
[-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Поскольку минимальный месяц (июль 2019 г.) находится в индексе 1, мне нужно добавить к нему -1 месяц, чтобы получить месяц, предшествующий ему, а именно июнь 2019 г.

Так что он может быть разбитым на:

(min(new_totalmonth) + relativedelta(months=-1)).strftime('%b %Y') = Jun 2019
(min(new_totalmonth) + relativedelta(months=0)).strftime('%b %Y') = Ju1 2019
(min(new_totalmonth) + relativedelta(months=1)).strftime('%b %Y') = Aug 2019
...
(min(new_totalmonth) + relativedelta(months=10)).strftime('%b %Y') = May 2019

Возьмите все эти значения и поместите их в список new_totalmonth

print(new_totalmonth)
['Jun 2019', 'Jul 2019', 'Aug 2019', 'Sep 2019', 'Oct 2019', 'Nov 2019', 'Dec 2019', 'Jan 2020', 'Feb 2020', 'Mar 2020', 'Apr 2020', 'May 2020']
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...