Работа с группами в пандах

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

df2 = pd.DataFrame(np.random.randint(0,3,size=(10, 4)),columns=['ONE', 'TWO', 'CARS', 'FOUR'])
df2['NAMES'] = ['Peter','Jon','Mary','Mary','Peter','Peter','BONIFACE','Michael','Lucy','Gilari']
df2['CARS'] = ['Mercedes','BMW','Ford','BMW','BMW','Dacia','Ford','Pontiac','Chevrolet','Tesla']

И группирую по машинам, например.

agrupe = df2.groupby(['CARS'])

Дело в том, что после того, как я сгруппировал его, я хочу работать с ним, например, в группе, созданной BMW, я хочу присвоить значение столбца 2 столбцу 4 из элементов, у которых есть 2 в столбце ONE. Посмотрим, научусь ли я им управлять:

g = agrupe.get_group('BMW')

И исходя из этого

     ONE TWO CARS  FOUR  NAMES
1    1    0  BMW     1    Jon
3    2    1  BMW     1   Mary
4    0    1  BMW     0  Peter

к этому:

    ONE  TWO CARS  FOUR  NAMES
1    1    0  BMW     1   Jon
3    2    1  BMW     1   Mary
4    0    1  BMW     1  Peter

person Borja_042    schedule 09.12.2016    source источник
comment
Не могли бы вы перефразировать: «Я хочу присвоить значение столбца 2 столбцу 4 из элементов, у которых есть 2 в столбце ONE. ` ? Столбец TWO или второй столбец = CARS? Кроме того, приведенный пример не соответствует тому, что вы говорите   -  person MMF    schedule 09.12.2016
comment
Извините, мой родной язык не английский. Я делаю группы по автомобилям, а затем проверяю значения другого столбца, скажем, столбца ONE. Значения, которые имеют 2 в столбце ONE, дадут свое значение из столбца TWO в столбец FOUR. Надеюсь теперь стало понятнее. Спасибо   -  person Borja_042    schedule 09.12.2016
comment
Не проблема. под col2 вы имеете в виду столбец TWO или df.columns[2]?   -  person MMF    schedule 09.12.2016
comment
Я только что отредактировал свой комментарий, я пропустил ввод. Я надеюсь, что теперь вы лучше меня понимаете @MMF,   -  person Borja_042    schedule 09.12.2016
comment
@fra044 - В столбце ONE нет 2, есть только 1,3,4. Вам нужна работа с группой BMW после agrupe.get_group('BMW')? Или работает со строками с BMW в df2?   -  person jezrael    schedule 09.12.2016
comment
@ fra044 Если jezrael понимает ваш вопрос, то он действителен. Если нет, то это некорректный вопрос :P   -  person Mohammad Yusuf    schedule 09.12.2016
comment
@jezrael Нет, приятель. Это индекс. Мой реальный df намного сложнее. Мне нужно, чтобы проверка один раз сделала группы значениями одного столбца и по одному доминирующему значению передала их значение столбца другому столбцу. Я знаю, это довольно запутанно :(. Теперь dfs более понятны.   -  person Borja_042    schedule 09.12.2016
comment
Так что подумайте, если в столбце ONE есть 0, тогда замените столбец FOUR на столбец TWO, верно?   -  person jezrael    schedule 09.12.2016
comment
@MohammadYusufGhazi - я много раз ошибался...   -  person jezrael    schedule 09.12.2016
comment
Нет, подумайте, если в столбце ОДИН есть 2 (например), затем передайте значение этого элемента из столбца ДВА в столбец ЧЕТЫРЕ.   -  person Borja_042    schedule 09.12.2016


Ответы (1)


Кажется, вам нужно groupby с пользовательской функцией f:

np.random.seed(100)
df2 = pd.DataFrame(np.random.randint(0,3,size=(10, 4)),columns=['ONE', 'TWO', 'CARS', 'FOUR'])
df2['NAMES'] = ['Peter','Jon','Mary','Mary','Peter','Peter','BONIFACE','Michael','Lucy','Gilari']
df2['CARS'] = ['Mercedes','BMW','Ford','BMW','BMW','Dacia','Ford','Pontiac','Chevrolet','Tesla']
print (df2)
   ONE  TWO       CARS  FOUR     NAMES
0    0    0   Mercedes     2     Peter
1    2    0        BMW     1       Jon
2    2    2       Ford     2      Mary
3    1    0        BMW     0      Mary
4    0    2        BMW     1     Peter
5    1    2      Dacia     0     Peter
6    0    1       Ford     1  BONIFACE
7    0    0    Pontiac     1   Michael
8    1    2  Chevrolet     2      Lucy
9    1    1      Tesla     2    Gilari
def f(x):
    if (x.name == 'BMW'):
        x.loc[x.ONE == 2, 'FOUR'] = x.TWO
    return x

agrupe = df2.groupby('CARS').apply(f)
print (agrupe)
   ONE  TWO       CARS  FOUR     NAMES
0    0    0   Mercedes     2     Peter
1    2    0        BMW     0       Jon
2    2    2       Ford     2      Mary
3    1    0        BMW     0      Mary
4    0    2        BMW     1     Peter
5    1    2      Dacia     0     Peter
6    0    1       Ford     1  BONIFACE
7    0    0    Pontiac     1   Michael
8    1    2  Chevrolet     2      Lucy
9    1    1      Tesla     2    Gilari

Лучшее решение - сначала выбрать все строки, где столбец CARS равен BMW, а столбец ONE равен 2, а затем изменить FOUR на столбец TWO:

df2.loc[(df2.CARS == 'BMW') & (df2.ONE == 2), 'FOUR'] = df2.TWO
print (df2)
   ONE  TWO       CARS  FOUR     NAMES
0    0    0   Mercedes     2     Peter
1    2    0        BMW     0       Jon
2    2    2       Ford     2      Mary
3    1    0        BMW     0      Mary
4    0    2        BMW     1     Peter
5    1    2      Dacia     0     Peter
6    0    1       Ford     1  BONIFACE
7    0    0    Pontiac     1   Michael
8    1    2  Chevrolet     2      Lucy
9    1    1      Tesla     2    Gilari

Или, если нужно изменить, если 2 в столбце ONE, измените столбец FOUR на столбец TWO:

np.random.seed(13)
df2 = pd.DataFrame(np.random.randint(0,3,size=(10, 4)),columns=['ONE', 'TWO', 'CARS', 'FOUR'])
df2['NAMES'] = ['Peter','Jon','Mary','Mary','Peter','Peter','BONIFACE','Michael','Lucy','Gilari']
df2['CARS'] = ['Mercedes','BMW','Ford','BMW','BMW','Dacia','Ford','Pontiac','Chevrolet','Tesla']
print (df2)
   ONE  TWO       CARS  FOUR     NAMES
0    2    0   Mercedes     0     Peter
1    2    2        BMW     1       Jon
2    0    2       Ford     0      Mary
3    2    2        BMW     2      Mary
4    1    1        BMW     1     Peter
5    0    2      Dacia     1     Peter
6    2    1       Ford     2  BONIFACE
7    0    0    Pontiac     0   Michael
8    2    2  Chevrolet     0      Lucy
9    1    1      Tesla     2    Gilari


df2.loc[df2.ONE == 2, 'FOUR'] = df2.TWO
print (df2)
   ONE  TWO       CARS  FOUR     NAMES
0    2    0   Mercedes     0     Peter
1    2    2        BMW     2       Jon
2    0    2       Ford     0      Mary
3    2    2        BMW     2      Mary
4    1    1        BMW     1     Peter
5    0    2      Dacia     1     Peter
6    2    1       Ford     1  BONIFACE
7    0    0    Pontiac     0   Michael
8    2    2  Chevrolet     2      Lucy
9    1    1      Tesla     2    Gilari
person jezrael    schedule 09.12.2016
comment
Это выглядит довольно мило. Дай мне проверить. Спасибо - person Borja_042; 09.12.2016
comment
Это не правильно. Я сгруппировал по машинам, а затем работал с BMW просто для примера. Дело в том, что после того, как я сгруппировал, я не знаю названия каждой группы, поэтому, если (x.name == 'BMW'): неверно, после удаления этой части функция вообще не работает. Я использовал эту часть def f(x): x.loc[x.ONE == 2, 'FOUR'] = x.TWO return x - person Borja_042; 09.12.2016
comment
Теперь, как это работает? def f(x): x.loc[x.ONE == 2, 'FOUR'] = x.TWO return x такой же и быстрее, как df2.loc[df2.ONE == 2, 'FOUR'] = df2.TWO - person jezrael; 09.12.2016
comment
Дело в том, что при последнем изменении элементы не группируются, поэтому вы меняете значение столбца FOUR во всей группе. - person Borja_042; 09.12.2016
comment
Извините, я не понимаю. При необходимости указать группу по значению (BMW) и значению 2 в столбце ONE можно использовать df2.loc[(df2.CARS == 'BMW') & (df2.ONE == 2), 'FOUR'] = df2.TWO. Если нет, то почему? Можете ли вы объяснить больше? - person jezrael; 09.12.2016
comment
Спецификация группы BMW была просто примером. Я создаю группы по имени столбца, а затем я должен использовать эту группу как небольшие кадры данных, это общая идея. Спасибо за ваши старания - person Borja_042; 09.12.2016
comment
хорошо, так что, если мой ответ был полезен, не забудьте принять его. Спасибо. - person jezrael; 09.12.2016