Присвоить одинаковый номер индекса для дублированных значений до n дубликатов - PullRequest
1 голос
/ 06 марта 2020

У меня есть следующий столбец, где значения дублируются любое количество раз:

FRUIT
Apples
Bananas
Bananas
Pear
Pear
Pear
Pear
Melon
Melon
Melon
Melon
Melon
Melon
Orange
Orange
Orange
Orange
Orange
Orange
Orange
Orange
Orange

Я хотел бы назначить номер индекса для каждого значения, однако для дублированных значений я хочу повторить этот номер индекса до 4 раз. Если значение появляется 10 раз, я хочу, чтобы индекс повторялся для первых четырех, затем индекс + 1 ко вторым четырем и так далее. Например:

Index    FRUIT
1        Apples
2        Bananas
2        Bananas
3        Pear
3        Pear
3        Pear
3        Pear
4        Melon
4        Melon
4        Melon
4        Melon
5        Melon
5        Melon
6        Orange
6        Orange
6        Orange
6        Orange
7        Orange
7        Orange
7        Orange
7        Orange
8        Orange

Вот моя попытка:

fruit = {'FRUIT':['Apples','Bananas','Bananas','Pear','Pear','Pear','Pear','Melon','Melon','Melon','Melon','Melon','Melon','Orange','Orange','Orange','Orange','Orange','Orange','Orange','Orange','Orange']}
fruit_df = pd.DataFrame(fruit)

index = 0
index_and_fruit = []
for (columnName, columnData) in fruit_df.iteritems():
    fruit_list = fruit_df['FRUIT'].tolist()
    index = index + 1
    for i in fruit_list:
        if fruit_list.count(i) >= 4:
            index = index + 1
            index_with_fruit_list = {i:index}
            index_and_fruit.append(index_with_fruit_list)
            if fruit_list.count(i) >= 8:
                index_with_fruit_list = {i:index}
                index_and_fruit.append(index_with_fruit_list)
        else: 
            index_with_fruit_list = {i:index}
            index_and_fruit.append(index_with_fruit_list)
            print(index_and_fruit)

Ответы [ 2 ]

1 голос
/ 06 марта 2020

Мой дубль при условии, что фрукты упорядочены:

fruits = ['Apples', 'Bananas', 'Bananas', 'Pear', 'Pear', 'Pear',
    'Pear', 'Melon', 'Melon', 'Melon', 'Melon', 'Melon', 'Melon',
    'Orange', 'Orange', 'Orange', 'Orange', 'Orange', 'Orange',
    'Orange', 'Orange', 'Orange']

# The index for the next fruit.
current_index = 0

# The last fruit we've seen.
last_fruit = None

# The number of times we've assigned the current index to the last
# fruit already.
fruit_count = 0

for fruit in fruits:
    if fruit != last_fruit or fruit == last_fruit and fruit_count >= 4:
        # This is either
        #   (a) a new fruit, or
        #   (b) a repeated fruit to which we've assigned the current
        #       index four times already.
        # In both cases, we want to skip to the next index.
        current_index += 1
        fruit_count = 0

    last_fruit = fruit
    fruit_count += 1

    print(current_index, fruit, f"(fruit_count={fruit_count})")
1 голос
/ 06 марта 2020

Вы можете использовать накопление для формирования групп, вычисляя относительный индекс каждого фрукта в своей группе. Это позволяет вам установить максимальный размер группы и сбросить относительный индекс либо при изменении фруктов r при достижении максимума.

С помощью этой группировки вы можете назначать последовательные индексы на основе первого элемента каждой группы. (снова используя накопление):

fruits = ['Apples','Bananas','Bananas','Pear','Pear','Pear','Pear','Melon','Melon',
          'Melon','Melon','Melon','Melon','Orange','Orange','Orange','Orange','Orange',
          'Orange','Orange','Orange','Orange']

from itertools import accumulate

maxGroup = 4
indexes  = range(len(fruits))
byGroup  = accumulate(indexes,lambda i,f: (i+1)*(f>0 and i<maxGroup-1 and fruits[f-1]==fruits[f]))
indexes  = [i-1 for i in accumulate(int(g==0) for g in byGroup)]
indexAndFruit = [(i,f) for i,f in zip(indexes,fruits)]

вывод:

for i,f in indexAndFruit: print(i,f)

0 Apples
1 Bananas
1 Bananas
2 Pear
2 Pear
2 Pear
2 Pear
3 Melon
3 Melon
3 Melon
3 Melon
4 Melon
4 Melon
5 Orange
5 Orange
5 Orange
5 Orange
6 Orange
6 Orange
6 Orange
6 Orange
7 Orange

Чтобы проиллюстрировать, как это работает, давайте посмотрим, что будет производить итератор byGroup:

[0, 0, 1, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 0, 1, 2, 3, 0, 1, 2, 3, 0]

Каждая позиция, где индексация начинается с нуля, соответствует изменению фруктов или относительному индексу, достигающему максимума

Нули в этом списке соответствуют началу групп. Пометка их как 1 с 0 для других индексов даст следующий результат:

[1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1]

Если мы запустим кумулятивную сумму этих начальных позиций, мы получим (основанные на одном) индексы:

[1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8]

минус 1 дает нам нужные индексы, которые нам нужно только объединить с фруктами (используя zip):

[0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...