Предположим, у вас есть два списка, а именно indexes
и values
одинаковой длины.
Я хочу добавить столбец в существующий DataFrame, например. df["Values"]
используя эти списки, в частности, присваивая values[0]
всем строкам с индексом между 0
и indexes[0]
, затем values[1]
всем строкам с индексом между indexes[0]
и indexes[1]
и так далее...
На данный момент мне удалось получить этот результат только путем перебора всех фреймов данных с помощью метода df.iterrows()
, но это довольно медленно, когда размер фрейма данных (csv) составляет около 20 МБ.
Есть ли элегантный способ получить тот же результат, не используя цикл for, а используя метод pandas или аналогичный?
Вам следует предоставить небольшой мре . Посмотрите merge_asof. Например. вы можете попробовать что-то вроде (df
ваш фрейм данных): pd.merge_asof(df.reset_index(), pd.DataFrame({"index": indexes, "Values": values}), direction = "forward").assign(Values=lambda df: df["Values"].ffill()).drop(columns = "index")
.
Вы можете сделать что-то вроде:
df = pd.DataFrame({'Values': []})
partition1 = pd.Series([values[0] for _ in range(indexes[0])])
partition2 = pd.Series([values[1] for _ in range(indexes[0], indexes[1])])
df['Values'] = pd.concat([partition1, partition2], ignore_index=True)
и если у вас больше разделов, вы автоматизируете это с помощью цикла for, определяющего количество разделов.
Расширяю ответ Симоны:
def repeat(values, indexes):
"""
Create a new list filled with values from list "values" with the corresponding index from "indexes"
as the maximum index to fill up to.
Example:
Given values=[7,4,8] and indexes=[3,5,7] the value values[0]=7 should be repeated from index 0 to indexes[0]
in the new list, the value values[1]=4 should be repeated from indexes[0]+1 to indexes[1] and so on.
"""
if len(values) != len(indexes):
raise ValueError(f'Length of values and indexes has to be the same, got len(values) = {len(values)} and len(indexes) = {len(indexes)}')
expanded_indexes = indexes.copy()
expanded_indexes.insert(0, -1)
repetition = [values[j-1] for j in range(1, len(expanded_indexes)) for _ in range(expanded_indexes[j-1], expanded_indexes[j])]
return repetition
df = pd.DataFrame()
# insert other data in df
values = [7,4,8]
indexes = [3,5,7]
repeating_list = repeat(values, indexes)
df['Values'] = repeating_list
IIUC, вы можете использовать pandas.cut.
Включая правый индекс:
df = pd.DataFrame({"Data": range(10)})
indexes = [2, 4, 6, 8, 10]
values = [1, 2, 3, 4, 5]
df["Values"] = pd.cut(df.index, bins=[-1] + indexes, labels=values)
Data Values
0 0 1
1 1 1
2 2 1
3 3 2
4 4 2
5 5 3
6 6 3
7 7 4
8 8 4
9 9 5
Без учета правого индекса:
df["Values"] = pd.cut(df.index, bins=[-1] + indexes, labels=values, right=False)
Data Values
0 0 1
1 1 1
2 2 2
3 3 2
4 4 3
5 5 3
6 6 4
7 7 4
8 8 5
9 9 5
Предоставьте достаточно кода, чтобы другие могли лучше понять или воспроизвести проблему.