сделать уникальное перечисление для объединенных панд df - PullRequest
0 голосов
/ 21 ноября 2018

У меня есть несколько фреймов данных, где данные помечены в группах, скажем, так:

df1 = pd.DataFrame({'id':[1,3,7, 10,30, 70, 100, 300], 'name':[1,1,1,1,1,1,1,1], 'tag': [1,1,1, 2,2,2, 3,3]})
df2 = pd.DataFrame({'id':[2,5,6, 20, 50, 200, 500, 600], 'name': [2,2,2,2,2,2,2,2], 'tag':[1,1,1, 2, 2, 3,3,3]})
df3 = pd.DataFrame({'id':[4, 8, 9, 40, 400, 800, 900], 'name': [3,3,3,3,3,3,3], 'tag':[1,1,1, 2, 3, 3,3]})

В каждом фрейме данных тег присваивается в порядке возрастания идентификаторов (поэтому большие идентификаторы будут равны илибольшие метки).Я хочу пересчитать теги в объединенном фрейме данных,

df = pd.concat([df1, df2, df3])

, чтобы тег каждой группы был в порядке возрастания идентификаторов первого элемента каждого.Таким образом, группа, начинающаяся с id = 1, будет помечена 1 (то есть идентификаторы 1,3,7), группа, начинающаяся с id = 2, будет помечена 2 (то есть идентификаторы 2,5,6),группа, начинающаяся с 4, будет помечена как 3, группа, начинающаяся с 10, будет помечена как 4 и т. д.

Мне удалось получить (сложное!) решение:

1) Получить первую строку каждой группы, поместить их в кадр данных, отсортировать по id и создать новые теги:

dff = pd.concat([df1.groupby('tag').first(), df2.groupby('tag').first(), df3.groupby('tag').first()])
dff = dff.sort(['id'])
dff = dff.reset_index()
dff['new_tags'] = dff.index +1

2) Объединить этот кадр данных с начальными, drop_duplicates, чтобы сохранить новые тегистроки, упорядоченные по группам, затем распространяют новые теги:

df = pd.concat([dff, df1, df2, df3])
df = df.drop_duplicates(subset=['id', 'tag', 'name'])
df = df.sort(['name', 'tag'])
df = df.fillna(method = 'pad')

Новые теги - это именно то, что нужно, но мое решение кажется слишком сложным.Не могли бы вы предложить, как сделать проще?Я думаю, что я что-то упускаю!

Заранее спасибо,

М.

Ответы [ 2 ]

0 голосов
/ 21 ноября 2018

После объединения вы можете использовать groupby столбцы 'tag' и 'name' с transform и first в столбце 'id'.Затем sort_values этой серии и cumsum diff больше 0, например:

df = pd.concat([df1, df2, df3]).sort_values('id').reset_index(drop=True)
df['new'] = (df.groupby(['tag','name'])['id'].transform('first')
               .sort_values().diff().ne(0.).cumsum())

, и вы получите ожидаемый результат:

     id  name  tag  new
0     1     1    1    1
1     2     2    1    2
2     3     1    1    1
3     4     3    1    3
4     5     2    1    2
5     6     2    1    2
6     7     1    1    1
7     8     3    1    3
8     9     3    1    3
9    10     1    2    4
10   20     2    2    5
11   30     1    2    4
12   40     3    2    6
...

РЕДАКТИРОВАТЬ: избежатьиспользуя groupby, вы можете drop_duplicates и index получить индекс первых идентификаторов, создать новый столбец с инкрементным значением, используя loc и range, а затем ffill после sort_values для заполнениязначения:

df = pd.concat([df1, df2, df3]).sort_values('id').reset_index(drop=True)
list_ind = df.drop_duplicates(['name','tag']).index
df.loc[list_ind,'new'] = range(1,len(list_ind)+1)
df['new'] = df.sort_values(['tag','name'])['new'].ffill().astype(int)

и вы получите тот же результат

0 голосов
/ 21 ноября 2018

Используя pd.concat + keys, я разбиваю шаги

df=pd.concat([df1,df2,df3],keys=[0,1,2])
df=df.reset_index(level=0)#get the level=0 index 
df=df.sort_values(['tag','level_0']) # sort the value 

df['New']=(df['tag'].diff().ne(0)|df['level_0'].diff().ne(0)).cumsum()
df
Out[110]: 
   level_0   id  name  tag  New
0        0    1     1    1    1
1        0    3     1    1    1
2        0    7     1    1    1
0        1    2     2    1    2
1        1    5     2    1    2
2        1    6     2    1    2
0        2    4     3    1    3
1        2    8     3    1    3
2        2    9     3    1    3
3        0   10     1    2    4
4        0   30     1    2    4
5        0   70     1    2    4
3        1   20     2    2    5
4        1   50     2    2    5
3        2   40     3    2    6
6        0  100     1    3    7
7        0  300     1    3    7
5        1  200     2    3    8
6        1  500     2    3    8
7        1  600     2    3    8
4        2  400     3    3    9
5        2  800     3    3    9
6        2  900     3    3    9
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...