#python #sql #pandas #tsql #dataframe
#python #sql #pandas #tsql #фрейм данных
Вопрос:
Допустим, у нас есть фрейм данных df
df = pd.DataFrame({
"Id": [1, 2],
"Value": [2, 5]
})
df
Id Value
0 1 2
1 2 5
и некоторая функция f
, которая принимает элемент df
и возвращает фрейм данных.
def f(value):
return pd.DataFrame({"A": range(10, 10 value), "B": range(20, 20 value)})
f(2)
A B
0 10 20
1 11 21
Мы хотим применить f
к каждому элементу в df["Value"]
, и присоединить результат к df
, вот так:
Id Value A B
0 1 2 10 20
1 1 2 11 21
2 2 5 10 20
2 2 5 11 21
2 2 5 12 22
2 2 5 13 23
2 2 5 14 24
В T-SQL с табличной df
и табличнозначной функцией f
мы бы сделали это с помощью ПЕРЕКРЕСТНОГО ПРИМЕНЕНИЯ:
SELECT * FROM df
CROSS APPLY f(df.Value)
Как мы можем это сделать в pandas
?
Ответ №1:
Вы можете применить функцию к каждому элементу Value
в понимании списка и использовать pd.concat
для объединения всех результирующих фреймов данных. Также назначьте соответствующий Id
, чтобы его можно было позже использовать для merge
обоих фреймов данных:
l = pd.concat([f(row.Value).assign(Id=row.Id) for _, row in df.iterrows()])
df.merge(l, on='Id')
Id Value A B
0 1 2 10 20
1 1 2 11 21
2 2 5 10 20
3 2 5 11 21
4 2 5 12 22
5 2 5 13 23
6 2 5 14 24
Комментарии:
1. Надежный ответ. Я использую этот метод немного с похожими файлами из разных периодов времени для объединения данных в большую структуру данных.
2. Спасибо — я собирался использовать подобный подход, но подумал, что для этого может быть метод pandas. Не знал о
assign
— handy .3. Добро пожаловать, @Denziloe! Не забывайте, что вы можете согласиться, если это решило проблему за вас 🙂
Ответ №2:
Один из немногих случаев, которые я бы использовал DataFrame.iterrows
. Мы можем выполнять итерации по каждой строке, объединять декартово произведение вашей функции с исходным фреймом данных и одновременно fillna
с bfill
и ffill
:
df = pd.concat([pd.concat([f(r['Value']), pd.DataFrame(r).T], axis=1).bfill().ffill() for _, r in df.iterrows()],
ignore_index=True)
Что дает:
print(df)
A B Id Value
0 10 20 1.0 2.0
1 11 21 1.0 2.0
2 10 20 2.0 5.0
3 11 21 2.0 5.0
4 12 22 2.0 5.0
5 13 23 2.0 5.0
6 14 24 2.0 5.0