In truncate_before
:
def truncate_before(list_of_dfts, idx):
for dfts in list_of_dfts:
dfts = dfts[idx:]
print(dfts.head)
for-loop
создает локальную переменную dfts
, которая ссылается на кадры данных в list_of_dfts
. Но
dfts = dfts[idx:]
переназначает новое значение для dfts
. Это не изменяет DataFrame в list_of_dfts
.
См. Факты и мифы об именах и значениях Python, где подробно объясняется, как имена переменных связываются со значениями. и какие операции изменяют значения по сравнению с привязкой новых значений к именам переменных.
Вот несколько альтернатив:
Измените список на месте
def truncate_before(list_of_dfts, idx):
list_of_dfts[:] = [dfts[idx:] for dfts in list_of_dfts]
for dfts in list_of_dfts:
print(dfts.head)
поскольку присваивание list_of_dfts[:]
(которое вызывает list_of_dfts.__setitem__
) изменяет содержимое list_of_dfts
на месте.
import numpy as np
import pandas as pd
df_a = pd.DataFrame(np.random.rand(14,2), columns = list('XY'))
df_b = pd.DataFrame(np.random.rand(14,2), columns = list('XY'))
mylist = [df_a, df_b]
def truncate_before(list_of_dfts, idx):
list_of_dfts[:] = [dfts[idx:] for dfts in list_of_dfts]
print(mylist[0])
truncate_before(mylist, 11)
print(mylist[0])
показывает, что mylist[0]
было усечено. Однако обратите внимание, что df_a
по-прежнему ссылается на исходный DataFrame.
Вернуть список и переназначить результат mylist
или df_a, df_b
Использование возвращаемых значений может сделать ненужным изменение mylist
на месте.
Чтобы переназначить глобальные переменные df_a
, df_b
на новые значения, вы можете заставить truncate_before
возвращать список фреймов данных и переназначить df_a
и df_b
возвращаемому значению:
def truncate_before(list_of_dfts, idx):
return [dfts[idx:] for dfts in list_of_dfts]
mylist = truncate_before(mylist, 11) # or
# df_a, df_b = truncate_before(mylist, 11) # or
# mylist = df_a, df_b = truncate_before(mylist, 11)
Но обратите внимание, что, вероятно, нехорошо обращаться к DataFrames через mylist
, df_a
и df_b
, поскольку, как показывает приведенный выше пример, значения не остаются скоординированными автоматически. Использование mylist
должно быть достаточным.
Используйте метод DataFrame с параметром inplace, например df.drop
dfts.drop
(с inplace=True
) изменяет сам dfts
:
import numpy as np
import pandas as pd
df_a = pd.DataFrame(np.random.rand(14,2), columns = list('XY'))
df_b = pd.DataFrame(np.random.rand(14,2), columns = list('XY'))
mylist = [df_a, df_b]
def truncate_before(list_of_dfts, idx):
for dfts in list_of_dfts:
dfts.drop(dfts.index[:idx], inplace=True)
truncate_before(mylist, 11)
print(mylist[0])
print(df_a)
При изменении dfts
на месте оба значения в mylist
и df_a
и df_b
изменяются одновременно.
Обратите внимание, что dfts.drop
удаляет строки на основе значения метки индекса. Таким образом, приведенное выше полагается (предполагается), что dfts.index
уникален. Если dfts.index
не уникально, dfts.drop
может содержать больше строк, чем idx
строк. Например,
df = pd.DataFrame([1,2], index=['A', 'A'])
df.drop(['A'], inplace=True)
удаляет обе строки, делая df
пустым DataFrame.
Обратите также внимание на это предупреждение от основного разработчика Pandas относительно использования inplace
:
Мое личное мнение: я никогда не использую операции на месте. Синтаксис труднее читать и не дает никаких преимуществ.
Вероятно, это связано с тем, что под капотом dfts.drop
создается новый фрейм данных, а затем вызывается частный метод _update_inplace
для присвоения новых данных старому фрейму данных:
def _update_inplace(self, result, verify_is_copy=True):
"""
replace self internals with result.
...
"""
self._reset_cache()
self._clear_item_cache()
self._data = getattr(result,'_data',result)
self._maybe_update_cacher(verify_is_copy=verify_is_copy)
Поскольку временный result
должен был быть создан в любом случае, нет никакого преимущества в памяти или производительности операций «на месте» по сравнению с простым переназначением.
person
unutbu
schedule
30.01.2016