#python #pandas #dataframe
Вопрос:
Итак, у меня есть этот фрейм данных. Столбцы «Время» следуют последовательности, в которой указаны все недели, которые находятся между первой и последней строками, заполненными в столбце. Но одно из значений, т. е. W43-2021, отсутствует.
Как вставить новую строку, соответствующую W43-2021, при этом все остальные значения столбцов будут либо такими же, как у других, либо отсутствуют, а «Значения» равны 0. В основном, как показано ниже в кадре данных.
Я попытался использовать приведенный ниже подход для решения этой проблемы.
f = int(df['Time.[Week]'][0][1:3]) l = int(df['Time.[Week]'].iloc[-1][1:3]) check = list(df['Time.[Week]'].str[1:3]) check = list(map(int, check)) c = [] for i in range(f, l 1): if i not in check: c.append(i) for week in c: temp_df = pd.DataFrame(columns = df.columns) temp_df.loc[0, 'Time.[Week]'] = 'W' str(week) '-2021' df.append(temp_df)
Это не кажется наиболее подходящим способом решения проблемы, поскольку порядок нарушается из-за добавления фрейма данных в конце, и может быть несколько отсутствующих строк, которые могут возникнуть позже. Что может быть лучшим и более питоническим способом решения этого дела?
Также найдите код для запуска df, если это необходимо.
df = pd.DataFrame([[33534,9132,'Current','W41-2021',34], [33534,9132,'Current','W42-2021', 45], [33534,9132,'Current','W44-2021', 32], [33534,9132,'Current','W45-2021', 41], [33534,9132,'Current','W46-2021',49]], columns = ['Item', 'Location', 'Version', 'Time', 'Value'])
Ответ №1:
Вы можете использовать следующее:
# build missing values weeks = df['Time'].str.extract('(?lt;=W)(d )').astype(int) idx = [f'W{w}-2021' for w in range(weeks.min()[0], weeks.max()[0] 1)] # add missing values df2 = df.set_index('Time').reindex(idx).reset_index() # ffill, except 'Value' df2 = df2.combine_first(df2.drop(columns='Value').ffill())[df.columns]
выход:
gt;gt;gt; df2 Item Location Version Time Value 0 33534.0 9132.0 Current W41-2021 34.0 1 33534.0 9132.0 Current W42-2021 45.0 2 33534.0 9132.0 Current W43-2021 NaN 3 33534.0 9132.0 Current W44-2021 32.0 4 33534.0 9132.0 Current W45-2021 41.0 5 33534.0 9132.0 Current W46-2021 49.0
Ответ №2:
Воспользуйся —
df['week'] = df['Time'].str[1:3].astype(int) df2 = pd.DataFrame([ i for i in range(week.min(), week.max())], columns=['week']).merge(df, how='outer') fill_val = df['Time'].iloc[0] df2['Time'] = df2['Time'].fillna(fill_val[0] df2['week'].astype(str) fill_val[3:]) df2 = df2.fillna(0)
Выход
week Time Value 0 41 W41-2021 34.0 1 42 W42-2021 45.0 2 43 W43-2021 0.0 3 44 W44-2021 32.0 4 45 W45-2021 41.0 5 46 W46-2021 49.0
Ответ №3:
Ты можешь так поступить:
Код:
df = pd.DataFrame([[33534,9132,'Current','W41-2021',34], [33534,9132,'Current','W42-2021', 45], [33534,9132,'Current','W44-2021', 32], [33534,9132,'Current','W45-2021', 41], [33534,9132,'Current','W46-2021',49]], columns = ['Item', 'Location', 'Version', 'Time', 'Value']) new_df = df.copy(deep=True) new_df = new_df.append(pd.DataFrame([[33534,9132,'Current','W43-2021',0]],columns=['Item', 'Location', 'Version', 'Time', 'Value'])) new_df = new_df.sort_values("Time",ascending=True) print(new_df)
Поскольку время упорядочено, вы можете просто добавить новое значение, а затем отсортировать значения в соответствии со временем.
Выход:
Item Location Version Time Value 0 33534 9132 Current W41-2021 34 1 33534 9132 Current W42-2021 45 0 33534 9132 Current W43-2021 0 2 33534 9132 Current W44-2021 32 3 33534 9132 Current W45-2021 41 4 33534 9132 Current W46-2021 49
Ответ №4:
Вариант 1 с merge()
обработкой любых лет с фактическим количеством недель, НЕ сохраняйте тип столбца (целое число становится плавающим)
import pandas as pd df = pd.DataFrame([[33534, 9132, 'Current', 'W41-2021', 34], [33534, 9132, 'Current', 'W42-2021', 45], [33534, 9132, 'Current', 'W44-2021', 32], [33534, 9132, 'Current', 'W45-2021', 41], [33535, 5555, 'Current', 'W44-2022', 132], [33535, 5555, 'Current', 'W45-2022', 141], [33534, 9132, 'Current', 'W46-2021', 49]], columns=['Item', 'Location', 'Version', 'Time', 'Value']) def yproc(gd): year = gd.Time.iloc[0].split('-')[1] # get the year from the group # compose a complete sequence like WNN-YYYY from all week numbers in a particular year ts = pd.Series([f'W{x 1:02d}-{year}' for x in pd.Series(pd.date_range(f'{year}-01-01',f'{year}-12-31',freq='W')).index],name='Time') d = gd.merge(ts, how='outer').sort_values('Time') # merge the df with the sequence d['Value'].fillna(0, inplace=True) # fill the values in the added rows return d.fillna(method='ffill').fillna(method='bfill') # fill other fields and return y = df.Time.str.split('-', expand=True)[1] # make a sequence to group by year df1 = df1 = df.groupby(y, as_index=False, group_keys=False).apply(yproc) # grop by year and apply the function print(df1.iloc[40:60,:])
Выход:
Item Location Version Time Value 0 33534.0 9132.0 Current W41-2021 34.0 1 33534.0 9132.0 Current W42-2021 45.0 45 33534.0 9132.0 Current W43-2021 0.0 2 33534.0 9132.0 Current W44-2021 32.0 3 33534.0 9132.0 Current W45-2021 41.0 4 33534.0 9132.0 Current W46-2021 49.0 46 33534.0 9132.0 Current W47-2021 0.0 47 33534.0 9132.0 Current W48-2021 0.0 48 33534.0 9132.0 Current W49-2021 0.0 49 33534.0 9132.0 Current W50-2021 0.0 50 33534.0 9132.0 Current W51-2021 0.0 51 33534.0 9132.0 Current W52-2021 0.0 2 33535.0 5555.0 Current W01-2022 0.0 3 33535.0 5555.0 Current W02-2022 0.0 4 33535.0 5555.0 Current W03-2022 0.0 5 33535.0 5555.0 Current W04-2022 0.0 6 33535.0 5555.0 Current W05-2022 0.0 7 33535.0 5555.0 Current W06-2022 0.0 8 33535.0 5555.0 Current W07-2022 0.0 9 33535.0 5555.0 Current W08-2022 0.0
Вариант 2 с concat()
обработкой любых лет с фактическим количеством недель, сохраните тип столбца (т. е. целое число)
# df = ... def yproc(gd): year = gd.Time.iloc[0].split('-')[1] # get the year from the group # compose a complete sequence like WNN-YYYY from all actual week numbers in a particular year ts = pd.Series( [f'W{x 1:02d}-{year}' for x in range(pd.date_range(f'{year}-01-01', f'{year}-12-31', freq='W').size)], name='Time') repeated = pd.concat([gd.take([0])] * ts.size, ignore_index=True) # replicate one row nth times depend of weeks number repeated.Value, repeated.Time = 0, ts # replace Value with 0, Time with ts d = pd.concat([gd, repeated]).drop_duplicates(['Time'], keep='first').sort_values('Time') return d y = df.Time.str.split('-', expand=True)[1] # make a sequence to group by year df1 = df.groupby(y, as_index=False, group_keys=False).apply(yproc) # grop by year and apply the function print(df1.iloc[39:60, :])
Item Location Version Time Value 39 33534 9132 Current W40-2021 0 0 33534 9132 Current W41-2021 34 1 33534 9132 Current W42-2021 45 42 33534 9132 Current W43-2021 0 2 33534 9132 Current W44-2021 32 3 33534 9132 Current W45-2021 41 6 33534 9132 Current W46-2021 49 46 33534 9132 Current W47-2021 0 ...