Этот вопрос связан с ответом @jpp: s в Объединение файлов с похожим соглашением имен с фреймом данных и решением пометить более ранний поток ( Поместить csv-файлы в отдельные фреймы данных в зависимости от имя файла ) как дубликат, потому что три ответа в этой теме либо не работали (2/3), либо плохо (1/3).
Независимо от ответов, которые не работали, один ответ (мой ответ), как говорили, был низкого качества, потому что "использование concat
в цикле for явно не рекомендуется документами" .
Критикуемый метод :
dataframes = {}
for filename in filenames:
_df = pd.read_csv(filename)
key = filename[:3]
try:
dataframes[key] = pd.concat([dataframes[key], _df], ignore_index=True)
except KeyError:
dataframes[key] = _df
Принятый метод (dd
- это словарь, в котором каждое значение представляет собой список имен файлов, а каждый ключ - первые три символа каждого имени файла):
dict_of_dfs
for k, v in dd.items():
dict_of_dfs[k] = pd.concat([pd.read_csv(fn) for fn in v], ignore_index=True)
Теперь я согласен, что понимание списка в вызове concat
(принятый метод) на эффективнее , чем цикл for, где concat
вызывается для каждого DataFrame
.
Но значит ли это, что мы должны всегда создавать DataFrames
из нескольких источников данных, используя понимание списка в вызове concat
(или append
), и использование цикла for так бедно что на самом деле неправильно ? А как насчет читабельности? Я лично (конечно) думаю, что мой критикуемый метод более читабелен.
Если мы прочитаем pandas
документы в DataFrame.append
, мы узнаем, что ни для циклов, ни для составления списков не "рекомендуемые методы для генерации DataFrames":
Ниже, , хотя и не рекомендуемые методы для генерации DataFrames , показаны два способа генерации DataFrame из нескольких источников данных.
Менее эффективно:
>>> df = pd.DataFrame(columns=['A'])
>>> for i in range(5):
... df = df.append({'A': i}, ignore_index=True)
>>> df
A
0 0
1 1
2 2
3 3
4 4
Более эффективно:
>>> pd.concat([pd.DataFrame([i], columns=['A']) for i in range(5)],
... ignore_index=True)
A
0 0
1 1
2 2
3 3
4 4
Итак. Мои вопросы следующие:
Зацикливается и использует concat
на нескольких источниках данных для создания одного или нескольких экземпляров DataFrame
, поэтому плохо , что неправильно ?
Должны ли мы всегда использовать понимание списка в таком случае?
Документы, похоже, не рекомендуют использовать ни списки списков, ни цикл for, так каков рекомендуемый способ создания DataFrame
из нескольких источников данных?
Я очень ценю ваши ответы @piRSquared и @jpp. Я до сих пор не убежден в том, что категорическое отклонение циклов concat
в for как плохо до такой степени, что неправильно , в то время как списочные значения правильны и принят .
Учитывая следующие данные испытаний:
df = pd.DataFrame({'A': np.arange(0, 25000), 'B': np.arange(0, 25000)})
for i in range(0, 50):
df.to_csv('{}.csv'.format(i))
Методы:
def conc_inside_loop(filenames):
df = None
for filename in filenames:
if df is None:
df = pd.read_csv(filename)
continue
df = pd.concat([df, pd.read_csv(filename)], ignore_index=True)
return df
def conc_list_comprehension(filenames):
return pd.concat([pd.read_csv(filename) for filename in filenames], ignore_index=True)
Times:
>> %timeit -n 10 conc_inside_loop(glob.glob('*.csv'))
460 ms ± 15.4 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
>> %timeit -n 10 conc_list_comprehension(glob.glob('*.csv'))
363 ms ± 32.9 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
Очевидно, что понимание списка более эффективно (я уже говорил, что понимаю это). Но различия не огромны. Я не думаю, вы можете назвать один метод плохим до такой степени, что он будет неправильным , а другой правильный , учитывая различия, которые мы видим здесь.
Как сказал @piRSquared, последний вопрос слишком широкий. Но третий способ - использовать concat
вне цикла for:
def conc_outside_loop(filenames):
df_list = []
for filename in filenames:
df_list.append(pd.read_csv(filename))
return pd.concat(df_list, ignore_index=True)
>> %timeit -n 10 conc_outside_loop(glob.glob('*.csv'))
344 ms ± 23.4 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)