Как объединить или объединить ряды в dataframe без дублирования имен столбцов

#python #pandas

#python #панды

Вопрос:

Я пытаюсь объединить ряд, возвращаемый из функции, в фрейм данных, но я не хочу, чтобы столбцы дублировались. Как я могу это сделать? Полный набор данных составляет ~ 100 тыс. строк, и существует около 100 подмножеств (определенных в цикле с масками), так что, надеюсь, существует быстрое в вычислительном отношении решение. Использование Python 3.7

Пример

 import pandas as pd

def myfcn(row, data, val):
    z1 = row['y']   val
    z2 = row['x']*row['y']
    return pd.Series(
        {'fancy_column_name1': z1, 
         'fancy_column_name2': z2/val},
        name=row.name
    )
    

col1 = [1, 1.5, 3.1, 3.4, 2, -1]
col2 = [1, -3, 2, 8, 2.5, -1.3]
df = pd.DataFrame(list(zip(col1, col2)), columns=['x', 'y'])
display(df)

### In the real case, this is all in a loop with many subsets that 
### are created with masks amp; specific criteria; this is 
### simplified here
df_subset = df.iloc[[0,2,3]]
#display(df_subset)
out = df_subset.apply(myfcn, axis=1, args=(df_subset, 100))
df = pd.concat([df, out], axis=1)

df_subset2 = df.iloc[[5]]
out = df_subset2.apply(myfcn, axis=1, args=(df_subset2, 250))
df = pd.concat([df, out], axis=1)
display(df)
 

Вот родительский фрейм данных «df»
введите описание изображения здесь
Вот текущий результат
введите описание изображения здесь
, вот желаемый результат
введите описание изображения здесь
Как я могу удалить дублирующиеся имена столбцов, свернув данные в один и тот же столбец? Я хочу сохранить цифры, а не NAN. Никогда не будет случая, когда в строке сохранялось бы более одного числа, но может быть случай, когда чисел нет (тогда сохраните NaN).

Комментарии:

1. Вы ищете merge не concat

2. Я пытался merge = df1.merge(df2, left_index=True, right_index=True) , merge = df1.merge(df2, how='outer') но это не сработало

3. pd.merge это тяжелая операция. Вместо pd.concat просто использовать df = df.combine_first(out) . Он объединяет 2 фрейма данных, заполняя нулевые значения в одном фрейме данных ненулевыми значениями из другого фрейма данных. проверьте мой ответ для получения подробной информации.

Ответ №1:

панды.DataFrame.combine_first: объединить два объекта DataFrame, заполнив нулевые значения в одном DataFrame ненулевыми значениями из другого DataFrame. Индексы строк и столбцов результирующего фрейма данных будут объединением двух.

Просто замените df = pd.concat([df, out], axis=1) на —

 df = df.combine_first(out)
 

введите описание изображения здесь

Более подробная информация здесь.


Причина, по которой ваш заказ не сохраняется, заключается в том out , что в нем всего 2 столбца. Это те, которые в первую очередь заменяют значения nans. Поэтому они становятся первыми. Вы можете вставить пустые x и y перед out, чтобы решить эту проблему —

 out.insert(0, 'x', 0)
out.insert(1, 'y', 0)
df = df.combine_first(out)
 

Добавьте это в цикл, и я узнаю, исправлен ли теперь ваш порядок столбцов.

Комментарии:

1. это аккуратный трюк, моя единственная жалоба заключается в том, что он переупорядочивает столбцы

2. Ну, вы можете изменить их порядок, просто удерживая столбцы перед этим. проверьте мой обновленный ответ.

3. pd.merge — тяжелая тяжелая операция и совершенно не нужна для того, что вы хотите сделать. Я не думаю, что это должен быть правильный ответ, но остальное зависит от вас 🙂

4. Как мне добавить новые имена столбцов в cols ? OP — это упрощенный случай, но подмножества создаются в цикле, поэтому cols = df.columns они должны быть вне цикла, затем cols редактируются, чтобы добавить мои два новых имени столбцов, затем выполните df=df[cols]

5. получение исходного порядка столбцов cols = list(df.columns) в начале; выполнение работы; затем в конце выполняется cols.extend(['fancy_column_name1', 'fancy_column_name2'] , а затем df = df[cols] выполняет трюк, он отлично сохраняется. Большое вам спасибо за вашу помощь и терпение!

Ответ №2:

Выполните свои вычисления подстановки вместе, затем добавьте эти столбцы вместе, а затем объедините их в свой основной dataframe. Я немного изменил ваш код:

 def myfcn(row, data, val):
    z1 = row['y']   val
    z2 = row['x']*row['y']
    return pd.Series(
        {'fancy_column_name1': z1, 
         'fancy_column_name2': z2/val},
        name=row.name
    )
    

col1 = [1, 1.5, 3.1, 3.4, 2, -1]
col2 = [1, -3, 2, 8, 2.5, -1.3]
df = pd.DataFrame(list(zip(col1, col2)), columns=['x', 'y'])

df_subset = df.iloc[[0,2,3]]
#display(df_subset)
out1 = df_subset.apply(myfcn, axis=1, args=(df_subset, 100))
df_subset2 = df.iloc[[5]]
out2 = df_subset2.apply(myfcn, axis=1, args=(df_subset2, 250))
out = out1.append(out2)

df = pd.merge(df, out, left_index=True, right_index=True, how="left")
print(df)
 

вывод:

      x    y  fancy_column_name1  fancy_column_name2
0  1.0  1.0               101.0              0.0100
1  1.5 -3.0                 NaN                 NaN
2  3.1  2.0               102.0              0.0620
3  3.4  8.0               108.0              0.2720
4  2.0  2.5                 NaN                 NaN
5 -1.0 -1.3               248.7              0.0052