#python #pandas #list
#питон #панды #Список
Вопрос:
Я изо всех сил пытаюсь понять, как сделать следующее: у меня есть фрейм данных, который выглядит следующим образом (это немного сложнее, это всего лишь пример):
df = pd.DataFrame({'id' : ['id1','id2'], 'coverage' : ['1 2 3 4 5 6 7 8 9 10 11 13 14 15 16 17 18 19 20 40 41 42 43 44 45 46 47 48 49 50','1 2 3 4 5 6 7 8 9 10 100 101 102 103 104 105 106 107 108 109 110']})
И я хочу сгенерировать новый ключ, который содержит только min-max каждого сегмента, в основном это должно выглядеть так:
id coverage
0 id1 1 11 13 20 40 50
1 id2 1 10 100 110
Это простая проблема, но я не могу придумать никаких решений, я знаю, что map(lambda x:) может работать…
Спасибо!
Комментарии:
1. Очевидно, что это не так просто, учитывая вашу структуру данных :-).
Ответ №1:
Давайте попробуем:
# split the values and convert to integers
s = df['coverage'].str.split().explode().astype(int)
# continuous blocks
blocks = s.diff().ne(1).groupby(level=0).cumsum()
s['coverage'] = (s.groupby([s.index, blocks])
.agg(['min','max'])
.astype(str).agg(' '.join, axis=1)
.groupby(level=0).agg(' '.join)
)
Ответ №2:
Сначала разделите эти строки, а затем разбейте их на большую серию, сохранив индекс в качестве 'id'
столбца. Затем мы берем разницу между последовательными строками внутри каждой группы и проверяем, где она не равна 1
.
Разрежьте разнесенный ряд по этой маске, и он сдвинулся, чтобы получить начальную и конечную точки, затем groupby и agg(list)
(или ' '.join
), чтобы получить ваш результат.
# To numeric so values become numbers.
s = pd.to_numeric(df.set_index('id')['coverage'].str.split().explode())
m = s.groupby(level=0).diff().ne(1)
result = s[m | m.shift(-1).fillna(True)].groupby(level=0).agg(list)
id
id1 [1, 11, 13, 20, 40, 50]
id2 [1, 10, 100, 110]
Name: coverage, dtype: object
Комментарии:
1. Этот ответ кажется правильным, хотя возникает проблема, когда последовательность имеет число, которое является частью другой последовательности, т. Е.: [1 [..] 10, 2 […] 16] обеспечивает [1,10, 2, 16], когда ожидаемый результат должен быть [1, 16]. Тем не менее, спасибо!! OOpoopps неважно, это работает безупречно! Спасибо!!!
2. @JuanMacD хммм, в таком случае, я полагаю, вы могли бы отсортировать серию раньше, а затем разобраться с дубликатами (возможно, удалить их), а затем применить вышеизложенное, чтобы получить то, что вы хотите.