унікальні комбінації значень у вибраних стовпцях у фреймі даних pandas та підрахунку


108

У мене є дані у фреймі даних pandas наступним чином:

df1 = pd.DataFrame({'A':['yes','yes','yes','yes','no','no','yes','yes','yes','no'],
                   'B':['yes','no','no','no','yes','yes','no','yes','yes','no']})

Отже, мої дані виглядають так

----------------------------
index         A        B
0           yes      yes
1           yes       no
2           yes       no
3           yes       no
4            no      yes
5            no      yes
6           yes       no
7           yes      yes
8           yes      yes
9            no       no
-----------------------------

Я хотів би перетворити його на інший фрейм даних. Очікуваний результат може бути показаний у наступному скрипті python:

output = pd.DataFrame({'A':['no','no','yes','yes'],'B':['no','yes','no','yes'],'count':[1,2,4,3]})

Отже, очікуваний результат виглядає так

--------------------------------------------
index      A       B       count
--------------------------------------------
0         no       no        1
1         no      yes        2
2        yes       no        4
3        yes      yes        3
--------------------------------------------

Насправді я можу досягти, щоб знайти всі комбінації та підрахувати їх, використовуючи таку команду: mytable = df1.groupby(['A','B']).size()

Однак виявляється, що такі комбінації є в одній колонці. Я хотів би розділити кожне значення в комбінації на інший стовпець, а також додати ще один стовпець для результату підрахунку. Чи можна це зробити? Чи можу я отримати ваші пропозиції? Спасибі заздалегідь.

Відповіді:


174

Ви можете groupbyна cols 'A' і 'B' і зателефонувати, sizeа потім reset_indexі renameзгенерований стовпець:

In [26]:

df1.groupby(['A','B']).size().reset_index().rename(columns={0:'count'})
Out[26]:
     A    B  count
0   no   no      1
1   no  yes      2
2  yes   no      4
3  yes  yes      3

оновлення

Невелике пояснення, групуючи по 2 стовпцях, це групує рядки, де значення A і B однакові, ми називаємо, sizeщо повертає кількість унікальних груп:

In[202]:
df1.groupby(['A','B']).size()

Out[202]: 
A    B  
no   no     1
     yes    2
yes  no     4
     yes    3
dtype: int64

Тож тепер для відновлення згрупованих стовпців ми називаємо reset_index:

In[203]:
df1.groupby(['A','B']).size().reset_index()

Out[203]: 
     A    B  0
0   no   no  1
1   no  yes  2
2  yes   no  4
3  yes  yes  3

Це відновлює індекси, але агрегація розмірів перетворюється на сформований стовпець 0, тому ми повинні перейменувати це:

In[204]:
df1.groupby(['A','B']).size().reset_index().rename(columns={0:'count'})

Out[204]: 
     A    B  count
0   no   no      1
1   no  yes      2
2  yes   no      4
3  yes  yes      3

groupbyприймає аргумент, as_indexякий ми могли б встановити, щоб Falseвін не робив згруповані стовпці індексом, але це створює a, seriesі вам все одно доведеться відновлювати індекси тощо:

In[205]:
df1.groupby(['A','B'], as_index=False).size()

Out[205]: 
A    B  
no   no     1
     yes    2
yes  no     4
     yes    3
dtype: int64

2

Трохи пов’язаний, я шукав унікальні комбінації і придумав такий метод:

def unique_columns(df,columns):

    result = pd.Series(index = df.index)

    groups = meta_data_csv.groupby(by = columns)
    for name,group in groups:
       is_unique = len(group) == 1
       result.loc[group.index] = is_unique

    assert not result.isnull().any()

    return result

І якщо ви хочете лише стверджувати, що всі комбінації унікальні:

df1.set_index(['A','B']).index.is_unique

Не знав про set_index(). Продовжував намагатися використовувати groupby()для групування рядків з певною загальною парою стовпців. Дивно, дякую!
user3290553

0

Поміщення дуже приємної відповіді @ EdChum у функцію count_unique_index. Унікальний метод працює лише на серіях панд, а не на кадрах даних. Функція нижче відтворює поведінку унікальної функції в R:

унікальний повертає вектор, кадр даних або масив, як x, але з видаленими повторюваними елементами / рядками.

І додає кількість випадків за запитом OP.

df1 = pd.DataFrame({'A':['yes','yes','yes','yes','no','no','yes','yes','yes','no'],                                                                                             
                    'B':['yes','no','no','no','yes','yes','no','yes','yes','no']})                                                                                               
def count_unique_index(df, by):                                                                                                                                                 
    return df.groupby(by).size().reset_index().rename(columns={0:'count'})                                                                                                      

count_unique_index(df1, ['A','B'])                                                                                                                                              
     A    B  count                                                                                                                                                                  
0   no   no      1                                                                                                                                                                  
1   no  yes      2                                                                                                                                                                  
2  yes   no      4                                                                                                                                                                  
3  yes  yes      3

0

Я не робив перевірку часу з цим, але було цікаво спробувати. В основному перетворюють два стовпці в один стовпчик кортежів. Тепер перетворіть це у фрейм даних, виконайте 'value_counts ()', який знаходить унікальні елементи та підраховує їх. Знову поспішіть із застібкою-блискавкою та впорядкуйте стовпці в потрібному порядку. Можливо, ви можете зробити кроки більш елегантними, але робота з кортежами мені здається більш природною для цієї проблеми

b = pd.DataFrame({'A':['yes','yes','yes','yes','no','no','yes','yes','yes','no'],'B':['yes','no','no','no','yes','yes','no','yes','yes','no']})

b['count'] = pd.Series(zip(*[b.A,b.B]))
df = pd.DataFrame(b['count'].value_counts().reset_index())
df['A'], df['B'] = zip(*df['index'])
df = df.drop(columns='index')[['A','B','count']]
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.