Допустим, у меня есть набор данных Airbnb с кучей столбцов. Интерес представляют «neighbourhood_cleansed», «host_is_superhost» и «price». Я хочу найти район, в котором разница между средними ценами суперхостов и несуперхостов максимальна.
Я хочу знать, можно ли это сделать полностью с помощью функций панд.
Моя логика заключается в том, чтобы сначала сгруппировать по «neighbourhood_cleansed», затем отфильтровать объект группировки по суперхостам и не суперхостам, а затем использовать медианную функцию.
Я определил функцию func
def func(host_is_superhost, price):
superhost_prices = price[host_is_superhost == 't']
notsuperhost_prices = price[host_is_superhost == 'f']
return (superhost_prices.median() - notsuperhost_prices.median())
listings = pd.read_csv("https://storage.googleapis.com/public-data-337819/listings%202%20reduced.csv",low_memory=False)
neighbourhoods = listings.groupby('neighbourhood_cleansed')[['host_is_superhost', 'price']]
Когда я запускаю следующее:
neighbourhoods.apply(func)
Выданная ошибка
TypeError: func() missing 1 required positional argument: 'price'
Как мне это решить?
Есть ли у вас лучшие способы решения первоначального вопроса?
Ваш исходный func
ожидал два аргумента, но получил только один, поэтому вы получили сообщение об ошибке.
Чтобы понять, что происходит при использовании apply
, попробуйте этот пример:
Мы видим, что столбец 'source'
имеет только два значения.
listings["source"].unique()
Out: array(['city scrape', 'previous scrape'], dtype=object)
Давайте попробуем более простую версию func
с группировкой на 'source'
:
def func2(row):
print(type(row))
print(row.shape)
grpby = listings.groupby("source")[["host_is_superhost", "price"]]
grpby.apply(func2)
Распечатывает:
<class 'pandas.core.frame.DataFrame'>
(55934, 2)
<class 'pandas.core.frame.DataFrame'>
(32012, 2)
Это помогает нам понять, что при использовании apply
func2
передается один pd.DataFrame
объект различной длины.
Альтернативный подход, который должен достичь того, что вы хотите, может использовать pd.pivot_table
, чтобы изменить форму данных и вычислить медиану price
. (Обратите внимание, что «цена» не является числом и ее необходимо очистить, чтобы она была полезной). Например:
listings["price_cleaned"] = (
listings["price"].apply(lambda row: row.strip("$").replace(",", "")).astype(float)
)
pt = pd.pivot_table(
listings,
values = "price_cleaned",
index = "neighbourhood_cleansed",
columns = "host_is_superhost",
aggfunc = "median",
)
pt["diff"] = pt["t"] - pt["f"]
mask = pt["diff"] == pt["diff"].max()
print(pt.index[mask][0]) # there is only one neighborhood in this case
'Westminster'