Python * args возвращает данные, а не кортежи панд - PullRequest
0 голосов
/ 08 октября 2018

Есть функция, которая возвращает серию фреймов данных.

def frames():
  bla bla
  return df1, df2, df3, df4

Я хотел бы написать функцию, которая будет добавлять эти фреймы вместе без необходимости перечислять счетчик так, чтобыУ меня может быть больше или меньше кадров в будущем

def appender(*args):
   condition goes here
       append things that are true

Я бы хотел назвать его так, чтобы

appender(frames())

вернул полный кадр, который прошел условие.

Прямо сейчас функция frames () возвращает кортеж из четырех кадров.Можно ли легко распаковать кортеж?

Спасибо за любую помощь!

Clem

ОБНОВЛЕНИЕ Вот пример

def frames():

    df1 = pd.DataFrame()

    df2 = pd.DataFrame()

    df3 = pd.DataFrame(['not', 'empty'])

    df4 = pd.DataFrame(['not', 'empty'])

    return df1, df2, df3, df4

def appender(*args):
    main_frame = pd.DataFrame()
    for arg in args:
        if arg.empty != True:
            assignment_frame = assignment_frame.append(arg)

    return assignment_frame


appender(frames())

дает


AttributeError Traceback (последний последний вызов) в () ----> 1 appender (frames ())

в appender (* args) 2 main_frame= pd.DataFrame () 3 для arg в аргументах: ----> 4 if arg.empty! = True: 5 assignment_frame = assignment_frame.append (arg) 6

AttributeError: объект 'tuple' не имеетатрибут 'empty'

Ответы [ 2 ]

0 голосов
/ 08 октября 2018

Есть пара ошибок:

  1. Не забудьте распаковать в своих исходных аргументах функции.
  2. Ваше имя переменной для фрейма данных в appender изменяется, сохраняйте его согласованным.

Вот рабочий пример:

def appender(*args):
    df = pd.DataFrame()
    for arg in args:
        if arg.empty != True:
            df = df.append(arg)
    return df

appender(*frames())

Но pd.DataFrame.append в цикле неэффективен из-за ненужного копирования данных;это не рекомендуетсяБолее эффективный способ написания этого возможен через pd.concat и понимание списка:

def appender(*dfs):
    return pd.concat([df for df in dfs if not df.empty], ignore_index=True)

Использование ignore_index=True гарантирует, что ваш выходной фрейм данных будет иметь индекс pd.RangeIndex по умолчанию.

0 голосов
/ 08 октября 2018

Ваш оригинальный код работал бы, если бы вы вызывали его через appender(*frames()), но вы все равно получили бы ошибку, потому что assignment_frame должно быть main_frame.

Однако, есть даже более простойподход.Просто передайте коллекцию фреймов данных и воспользуйтесь списком с вашими условиями, чтобы отфильтровать их.

Обратите внимание, что ВЫ НЕ ХОТИТЕ СОЗДАТЬ ДАННЫЕ, ПРИЛОЖАЯ!Это называется квадратичной копией, потому что каждый раз, когда вы вызываете append, возвращается копия исходного кадра данных плюс вновь добавленный кадр данных.Это будет очень медленно .См. Сроки ниже.

def appender(dataframes):
    return pd.concat([df for df in dataframes if not df.empty])  # Optional: .reset_index()


>>> appender(frames())
       0
0    not
1  empty
0    not
1  empty

Время (concat vs append)

df = pd.DataFrame(np.random.randn(10, 10))

%timeit df2 = pd.concat([df] * 1000)
# 10 loops, best of 3: 54.7 ms per loop

%%timeit
df3 = pd.DataFrame()
for _ in range(1000):
    df3 = df3.append(df)
# 1 loop, best of 3: 1.28 s per loop

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