Python – найти максимальные нулевые значения при растяжении и замене на 0

У меня есть фрейм данных с датой и временем и столбцом. Мне нужно найти максимальное растяжение нулевых значений в «конкретной дате» и заменить его нулем. В приведенном ниже примере 1 января максимальное растягивающее нулевое значение равно 3 раза, поэтому я должен заменить этот ноль. Точно так же я должен повторить процесс для 2 января.

Примечание. Только максимальное количество нулевых значений должно быть заменено нулем, а не остальными.

Ниже приведены мои образцы данных:

Datetime            X
01-01-2018 00:00    1
01-01-2018 00:05    Nan
01-01-2018 00:10    2
01-01-2018 00:15    3
01-01-2018 00:20    2
01-01-2018 00:25    Nan
01-01-2018 00:30    Nan
01-01-2018 00:35    Nan
01-01-2018 00:40    4
02-01-2018 00:00    Nan
02-01-2018 00:05    2
02-01-2018 00:10    2
02-01-2018 00:15    2
02-01-2018 00:20    2
02-01-2018 00:25    Nan
02-01-2018 00:30    Nan
02-01-2018 00:35    3
02-01-2018 00:40    Nan
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
0
363
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Использовать:

#convert columns to floats and datetimes
df['X'] = df['X'].astype(float)
df['Datetime'] = pd.to_datetime(df['Datetime'], dayfirst=True)

#check missing values
s = df['X'].isna()
#create consecutive groups 
g = s.ne(s.shift()).cumsum()
#get dates from datetimes
dates = df['Datetime'].dt.date

#get counts of consecutive NaNs
sizes = s.groupby([g[s], dates[s]]).transform('count')

#compare max count per dates to mask
mask = sizes.groupby(dates).transform('max').eq(sizes)

#set 0 by mask
df.loc[mask, 'X'] = 0

print (df)
              Datetime    X
0  2018-01-01 00:00:00  1.0
1  2018-01-01 00:05:00  NaN
2  2018-01-01 00:10:00  2.0
3  2018-01-01 00:15:00  3.0
4  2018-01-01 00:20:00  2.0
5  2018-01-01 00:25:00  0.0
6  2018-01-01 00:30:00  0.0
7  2018-01-01 00:35:00  0.0
8  2018-01-01 00:40:00  4.0
9  2018-01-02 00:00:00  NaN
10 2018-01-02 00:05:00  2.0
11 2018-01-02 00:10:00  2.0
12 2018-01-02 00:15:00  2.0
13 2018-01-02 00:20:00  2.0
14 2018-01-02 00:25:00  0.0
15 2018-01-02 00:30:00  0.0
16 2018-01-02 00:35:00  3.0
17 2018-01-02 00:40:00  NaN

Обновлено: вы можете создать filtered список всех дат и времени для замены и цепочки вместе с маской для проверки отсутствующих значений с помощью & для побитового И:

sizes = s.groupby([g[s & m], dates[s & m]]).transform('count')

Все вместе:

df['X'] = df['X'].astype(float)
df['Datetime'] = pd.to_datetime(df['Datetime'], dayfirst=True)

#check missing values
s = df['X'].isna()
#create consecutive groups 
g = s.ne(s.shift()).cumsum()
#get dates from datetimes
dates = df['Datetime'].dt.floor('d')

filtered = ['2018-01-01','2019-01-01']
m = dates.isin(filtered)

#get counts of consecutive NaNs
sizes = s.groupby([g[s & m], dates[s & m]]).transform('count')

#compare max count per dates to mask
mask = sizes.groupby(dates).transform('max').eq(sizes)

#set 0 by mask
df.loc[mask, 'X'] = 0

print (df)
              Datetime    X
0  2018-01-01 00:00:00  1.0
1  2018-01-01 00:05:00  NaN
2  2018-01-01 00:10:00  2.0
3  2018-01-01 00:15:00  3.0
4  2018-01-01 00:20:00  2.0
5  2018-01-01 00:25:00  0.0
6  2018-01-01 00:30:00  0.0
7  2018-01-01 00:35:00  0.0
8  2018-01-01 00:40:00  4.0
9  2018-01-02 00:00:00  NaN
10 2018-01-02 00:05:00  2.0
11 2018-01-02 00:10:00  2.0
12 2018-01-02 00:15:00  2.0
13 2018-01-02 00:20:00  2.0
14 2018-01-02 00:25:00  NaN
15 2018-01-02 00:30:00  NaN
16 2018-01-02 00:35:00  3.0
17 2018-01-02 00:40:00  NaN

Привет Израэль, спасибо за ваш комментарий. Что делать, если у меня есть данные за один год с 5-минутными временными метками, и я хочу применить этот процесс только для нескольких выбранных дат, а не для каждой даты?

AB14 09.04.2019 10:26

интересный вопрос.

Мое решение написано на scala, но я уверен, что ему есть эквивалент на python. Первое - настройки. Я использовал case class KV; в вашем примере ключом будет дата, а значением будет столбец X.

import org.apache.spark.sql.expressions.Window
import org.apache.spark.sql.{functions => F}

case class KV(k: String, v: Double)
val ds = Seq(("a", 0.0),
    ("a", Double.NaN),
    ("a", Double.NaN),
    ("b", Double.NaN),
    ("b", Double.NaN)).toDF("k", "v").as[KV]
val win = Window.partitionBy("k")

def countConsecutiveNans(s: String, iter: Iterator[KV]): Int = {
  (0 /: iter)((cnt: Int, kv: KV) => if (kv.v.isNaN) cnt+1 else 0)
}
ds.groupByKey(kv => kv.k).mapGroups(countConsecutiveNans)

Результирующий набор данных:

+-----+
|value|
+-----+
|    2|
|    2|
+-----+

Надеялся, что это помогло!

Другие вопросы по теме