#python-3.x #pandas #dataframe #pandas-groupby
#python-3.x #pandas #фрейм данных #pandas-groupby
Вопрос:
Наличие pandas df, который выглядит следующим образом:
x column word size y
0 1552 0 word1 218 2
1 1775 1 word2 53 2
2 1999 2 word3 163 2
3 2200 3 word4 142 2
4 2345 4 word5 129 2
Я хотел бы сгруппировать строки на основе условия:
abs(current_row_x current_row_size - next_row_x) < 10
Итак, желаемый df здесь будет:
x column word size y
0 1552 0 word1 word2 271 2
1 1999 2 word3 163 2
3 2200 3 word4 word5 271 2
К настоящему времени я уже пробовал следующее:
df = df.groupby((abs(df.x df.size - df.x.shift(1)) < 10).cumsum()).agg({'y':'min', 'x':'min', 'size':'sum', 'column':'min', 'word':' '.join})
Но результат df не совсем то, что я ожидаю, а также условие groupby, похоже, игнорируется.
Любой возможный подход к этому? Спасибо
Комментарии:
1. Вы уверены, что это условие настроено правильно? Мой вывод не соответствует.
2. Группа на основе
abs(current_row_x current_row_size - next_row_x) < 10
— это то, чего я хочу достичь. x — это место, где начинается слово, size — это размер слова. Поэтому, если размер x достаточно близок к следующему слову ( x из следующей строки df), я хочу их сгруппировать. Возможноdf = df.groupby((abs(df.x df.size - df.x.shift(1)) < 10).cumsum()).agg({'y':'min', 'x':'min', 'size':'sum', 'column':'min', 'word':' '.join})
, подход совершенно неправильный. Я пробовал разные подходы, но безуспешно. Цель состоит в том, чтобы получить желаемый df.
Ответ №1:
Я не получаю тот же результат, но попробуйте:
s = abs(df['x'] df['size'] - df['x'].shift(-1)) < 10
df = df.groupby(s).agg({'x' : 'first', 'column' : 'first',
'word' : lambda x: ' '.join(list(x)), 'size' : 'sum', 'y' : 'first'})
df
Out[1]:
x column word size y
False 1775 1 word2 word3 word5 345 2
True 1552 0 word1 word4 360 2
В качестве альтернативы, с .groupby
помощью и .cumcount
:
s = df.groupby((abs(df['x'] df['size'] - df['x'].shift(-1)) < 10)).cumcount()
df = df.groupby(s).agg({'x' : 'first', 'column' : 'first',
'word' : lambda x: ' '.join(list(x)), 'size' : 'sum', 'y' : 'first'})
df
Out[2]:
x column word size y
0 1552 0 word1 word2 271 2
1 1999 2 word3 word4 305 2
2 2345 4 word5 129 2
наконец, с .cumsum()
помощью (кажется, я получаю все, кроме выходных данных, которые вы опубликовали 🙂 !):
s = ((abs(df['x'] df['size'] - df['x'].shift(-1)) < 10)).cumsum()
df = df.groupby(s).agg({'x' : 'first', 'column' : 'first',
'word' : lambda x: ' '.join(list(x)), 'size' : 'sum', 'y' : 'first'})
df
Out[2]:
x column word size y
1 1552 0 word1 word2 word3 434 2
2 2200 3 word4 word5 271 2
Ответ №2:
После нескольких часов борьбы я заставил это работать.
Построение из этого df:
x column word size y
0 1552 0 word1 218 2
1 1775 1 word2 53 2
2 1999 2 word3 163 2
3 2200 3 word4 142 2
4 2345 4 word5 129 2
Первое, что я сделал, это добавил еще один столбец x1, представляющий сумму x и size:
df["x1"] = df["x"] df["size"]
Итак, теперь мой df выглядит так:
x column word size y x1
0 1552 0 word1 218 2 1770
1 1775 1 word2 53 2 1828
2 1999 2 word3 163 2 2162
3 2200 3 word4 142 2 2342
4 2345 4 word5 129 2 2474
Теперь я выполняю группировку с этим условием (df.x - df.x1.shift(1)) > 10)
:
df = df.groupby(((df.x - df.x1.shift(1)) > 10).cumsum()).agg({'y':'min', 'x':'min', 'size':'sum', 'column':'min', 'word':' '.join})
И результат будет ожидаемым:
y x size column word
0 2 1552 271 0 word1 word2
1 2 1999 163 2 word3
2 2 2200 271 3 word4 word5
Получилось, но я действительно не знаю, почему условие (abs(df.x df.size - df.x.shift(1)) < 10)
объединения не выполнялось. Может быть, кто-то с большим опытом может объяснить.