Создайте новый столбец в существующий столбец и добавьте значение через определенный интервал

#python #pandas

#python #pandas

Вопрос:

Я пытаюсь создать новый столбец на основе моего первого столбца. Например,

  I have a list of a = ["A", "B", "C"] and existing dataframe
 Race          Boy          Girl  
  W             0            1
  B             1            0
  H             1            1
  W             1            0
  B             0            0
  H             0            1
  W             1            0
  B             1            1
  H             0            1
  

Моя цель — создать новый столбец и добавить к нему значение на основе интервалов W, B, H. Чтобы конечный результат выглядел как:

   Race          Boy          Girl     New Column
  W             0            1           A 
  B             1            0           A
  H             1            1           A
  W             1            0           B
  B             0            0           B 
  H             0            1           B
  W             1            0           C
  B             1            1           C
  H             0            1           C
  

Интервал W, B, H согласован, и я хочу добавлять новое значение в новый столбец каждый раз, когда я вижу W. Данные длиннее этого.

Я перепробовал все возможные способы, но не смог придумать код. Я буду рад, если кто-нибудь сможет помочь, а также объяснить процесс. Спасибо

Комментарии:

1. Сколько W существует и сколько из этих новых значений A , B C у вас есть в наличии?

2. Извините, есть 67 Ws и 67 A B C

3. Количество Ws в dataframe совпадает с количеством значений, которые у меня есть в списке для нового столбца

Ответ №1:

Вот что вы можете сделать:

Используйте цикл для создания списка, повторяющегося для столбца.

 for i in len(dataframe['Race']):
    #Create list for last column
  

Как только у вас будет этот список, вы можете добавить его в список с помощью:

 dataframe['New Column'] = list
  

Комментарии:

1. Здесь говорится TypeError: 'int' object is not iterable

Ответ №2:

возможно, это работает..

 list = ['A','B','C',....]

i=-1
for entry in dataframe:
    if entry['Race'] = 'W':
        i =1 
    entry['new column'] = list[i]

  

также, если новый список столбцов очень большой для ввода, вы можете использовать понимание списка:

 list = [x for x in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ']
  

Комментарии:

1. Вы if entry['Race'] == 'W' ошибаетесь. сама запись является Race.

Ответ №3:

Если ваш W, B, H находится в этом точном порядке и завершает inteval, вы можете использовать np.repeat . Как и в вашем комментарии, np.repeat было бы достаточно только.

 import numpy as np

a = ["A", "B", "C"] #list
n = df.Race.nunique() # length of each interval
df['New Col'] = np.repeat(a, n)

In [20]: df
Out[20]:
  Race  Boy  Girl New Col
0    W    0     1       A
1    B    1     0       A
2    H    1     1       A
3    W    1     0       B
4    B    0     0       B
5    H    0     1       B
6    W    1     0       C
7    B    1     1       C
8    H    0     1       C
  

Комментарии:

1. Спасибо за вашу помощь, и да, они расположены в точном порядке, но вместо 3 ( W,H,B ) у меня их 17. Когда я запускаю код, он говорит ValueError: Length of values does not match length of index

2. Я изменил 3 на 67, чтобы соответствовать длине моего списка, и 9 на 1139, чтобы соответствовать длине моего массива данных, но все равно получаю ту же ошибку

3. @Eniola может быть, проверьте мой ответ ниже (выше?)? мне любопытно, что дает вам ваши полные данные.

4. Длина интервала на самом деле равна 17, а длина всех данных равна 1139 (67*17).

5. @Eniola: если это так, работает ли это: df['New Col'] = np.repeat(a, 17) где a находится список

Ответ №4:

Вот способ с pandas. Он увеличивается каждый раз, когда вы видите новый ‘W’ и обрабатывает недостающие значения Race.

 # use original post's definition of df
df['New Col'] = (
    (df['Race'] == 'W')              # True (1) for W; False (0) otherwise
    .cumsum()                        # increments each time you hit True (1)
    .map({1: 'A', 2: 'B', 3: 'C'})   # 1->A, 2->B, ...
)
print(df)

  Race  Boy  Girl   New Col
0    W    0     1         A
1    B    1     0         A
2    H    1     1         A
3    W    1     0         B
4    B    0     0         B
5    H    0     1         B
6    W    1     0         C
7    B    1     1         C
8    H    0     1         C
  

Ответ №5:

Существует несколько способов решения этой проблемы. Вы можете выполнять итерации по фрейму данных и присваивать значения новому столбцу через каждый интервал.

Вот подход, который, я думаю, сработает.

 #setting up the DataFrame you referred in the example

import pandas as pd
df = pd.DataFrame({'Race':['W','B','H','W','B','H','W','B','H'],
                   'Boy':[0,1,1,1,0,0,1,1,0],
                   'Girl':[1,0,1,0,0,1,0,1,1]})

#if you have 3 values to assign, create a list say A, B, C
#By creating a list, you have to manage only the list and the frequency
a = ['A','B','C']

#iterate thru the dataframe and assign the values in batches

for (i,row) in df.iterrows():      #the trick is to assign for loc[i]
    df.loc[i,'New'] = a[int(i/3)]  #where i is the index and assign value in list a
                                   #note: dividing by 3 will distribute equally

print(df)
  

Результатом этого будет:

   Race  Boy  Girl New
0    W    0     1   A
1    B    1     0   A
2    H    1     1   A
3    W    1     0   B
4    B    0     0   B
5    H    0     1   B
6    W    1     0   C
7    B    1     1   C
8    H    0     1   C
  

Я вижу, что вы пытаетесь получить решение, которое работает для 17 наборов записей. Вот код, и он работает правильно.

 import pandas as pd
df = pd.DataFrame({'Race':['W','B','H']*17,
                   'Boy':[0,1,1]*17,
                   'Girl':[1,0,1]*17})

#in the DataFrame, you can define the Boy and Girl value
#I think Race values are repeating so I just repeated it 17 times    

#define a variable from a thru z
a = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'

for (i,row) in df.iterrows():
    df.loc[i,'New'] = a[int(i/3)] #still dividing it by 3 equal batches
    
print(df)
  

Я не печатал для всех 17 наборов. Я только что сделал с 7 наборами. Результат все тот же.

    Race  Boy  Girl New
0     W    0     1   A
1     B    1     0   A
2     H    1     1   A
3     W    0     1   B
4     B    1     0   B
5     H    1     1   B
6     W    0     1   C
7     B    1     0   C
8     H    1     1   C
9     W    0     1   D
10    B    1     0   D
11    H    1     1   D
12    W    0     1   E
13    B    1     0   E
14    H    1     1   E
15    W    0     1   F
16    B    1     0   F
17    H    1     1   F
18    W    0     1   G
19    B    1     0   G
20    H    1     1   G
  

Ответ №6:

Старый способ pythonic: используйте функцию!

 In [18]: df                                                                     
Out[18]: 
  Race  Boy  Girl
0    W    0     1
1    B    1     0
2    H    1     1
3    W    1     0
4    B    0     0
5    H    0     1
6    W    1     0
7    B    1     1
8    H    0     1
  

Функция:

 def make_new_col(race_col, abc): 
    race_col = iter(race_col)  
    abc = iter(abc)
    new_col = [] 
    while True:
        try:
            race = next(race_col)
        except:
            break 
        if race == 'W': 
            abc_value = next(abc) 
            new_col.append(abc_value) 
        else: 
            new_col.append(abc_value) 
    return new_col
  

Затем выполните:

 abc = ['A', 'B', 'C']
df['New Column'] = make_new_col(df['Race'], abc)
  

Вы получаете:

 In [20]: df                                                                     
Out[20]: 
  Race  Boy  Girl New Column
0    W    0     1          A
1    B    1     0          A
2    H    1     1          A
3    W    1     0          B
4    B    0     0          B
5    H    0     1          B
6    W    1     0          C
7    B    1     1          C
8    H    0     1          C
  

Комментарии:

1. Я запустил этот код, и я получил ошибку StopIteration:

2. Ошибка возникает при abc_value = next(countyNames)

3. @Eniola вероятно, это связано с тем, что число W s не равно числу A, B, C , … Можете ли вы перепроверить??

4. Я также отредактировал функцию, чтобы вам не приходилось касаться ее внутри. Просто скопируйте вставку и укажите два аргумента: df['Race'] и abc соответственно вашим переменным.

5. О!! я только что увидел реальную проблему. Это моя ошибка при копировании и вставке моего кода! Вы должны поместить return new_col на тот же уровень, что и while True цикл.