#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