pandas dataframe заменяет NaN на 0, когда имя столбца в определенном диапазоне дат - PullRequest
0 голосов
/ 29 мая 2018

У меня есть такой кадр данных:

time A      time B      2017-11  2017-12  2018-01  2018-02          
2017-01-24  2020-01-01  NaN      NaN      NaN      NaN
2016-11-28  2020-01-01  NaN      4.0      2.0      2.0
2017-03-18  2017-12-21  NaN      NaN      NaN      NaN

Я хочу заменить все NaN на 0, когда имя столбца между временем A и временем B. Например, для третьей строки, диапазон времени от 2017От -03-18 до 2017-12-21, поэтому данные в третьей строке с именем столбцов между этим диапазоном, если он равен NaN, замените его на 0, в противном случае оставайтесь прежними.Надежды свои ясно.Спасибо

Ответы [ 2 ]

0 голосов
/ 29 мая 2018

Возможно, не лучшее решение, однако оно работает.

Вот мой тестовый образец:

d = pd.DataFrame([
    {"time A": "2017-01-24", "time B": np.nan,       "2016-11": np.nan, "2016-12": np.nan, "2017-01": np.nan, "2017-02": np.nan},
    {"time A": "2016-11-28", "time B": np.nan,       "2016-11": np.nan, "2016-12": 4,      "2017-01": 2,      "2017-02": 2},
    {"time A": "2016-12-18", "time B": "2017-01-01", "2016-11": np.nan, "2016-12": np.nan, "2017-01": np.nan, "2017-02": np.nan},
])

d["time B"].fillna("2020-01-01", inplace=True)
d.set_index(["time A", "time B"], inplace=True)

Исходная таблица :

time A      time B      2016-11  2016-12  2017-01  2017-02          
2017-01-24  2020-01-01  NaN      NaN      NaN      NaN
2016-11-28  2020-01-01  NaN      4.0      2.0      2.0
2016-12-18  2017-01-01  NaN      NaN      NaN      NaN

Похоже, time A - это дата открытия, а time B - это дата закрытия или что-то в этом роде.Таким образом, для удобства я заполнил пропущенную time B любой будущей датой, например '2020-01-01'

Мне не нравится работать с сводными таблицами, поэтому я использовал df.stack () чтобы сложить его и отформатировать столбцы даты:

d_stack = d.stack(dropna=False).reset_index()
d_stack.columns = ["time A", "time B", "month", "value"]

for col in ["time A", "time B"]:
    d_stack[col] = pd.to_datetime(d_stack[col], format="%Y-%m-%d", errors="ignore")

d_stack["month"] = pd.to_datetime(d_stack["month"], format="%Y-%m", errors="ignore")

Теперь удобнее заполнять пропущенные значения

def fill_existing(x):
    if (x["time A"] <= x["month"] <= x["time B"] and
            np.isnan(x["value"])):
        return 0
    else:
        return x["value"]

d_stack["value"] = d_stack.apply(fill_existing, axis=1)

Вывод :

    time A      time B      month       value
0   2017-01-24  2020-01-01  2016-11-01  NaN
1   2017-01-24  2020-01-01  2016-12-01  NaN
2   2017-01-24  2020-01-01  2017-01-01  NaN
3   2017-01-24  2020-01-01  2017-02-01  0.0

Наконец, отформатируйте month back и pd.pivot_table , чтобы вернуться к исходному формату таблицы:

d_stack["month"] = d_stack["month"].apply(lambda x: x.strftime("%Y-%m"))
pd.pivot_table(d_stack, columns="month", index=["time A", "time B"],
               values="value", aggfunc=np.sum)

Результат :

time A      time B      2016-12  2017-01  2017-02
2016-11-28  2020-01-01  4.0      2.0      2.0
2016-12-18  2017-01-01  NaN      0.0      NaN
2017-01-24  2020-01-01  NaN      NaN      0.0
0 голосов
/ 29 мая 2018

попробуйте этот код:

newdf=df[(df.date>some_date) & (df.date<somedate)]
newdf.fillna(0)

newdf - это тот кадр данных, который вы ищете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...