Как сгруппировать и повернуть кадр данных с ненулевыми значениями c - PullRequest
2 голосов
/ 20 апреля 2020

Я использую Python, и у меня есть набор данных из 6 столбцов, R, R c, J, T, Ca и Cb. Мне нужно «агрегировать» по столбцам «R», затем «J», чтобы для каждого R каждая строка представляла собой уникальное «J». R c является характеристикой c для R. Ca и Cb являются характеристиками для T. Это будет иметь больше смысла, глядя на таблицу ниже.

Мне нужно go от:

#______________________            ________________________________________________________________
#| R  Rc  J  T  Ca  Cb|           |# R  Rc  J  Ca(T=1)  Ca(T=2)  Ca(T=3)  Cb(T=1)  Cb(T=2)  Cb(T=3)|
#| a   p  1  1  x    d|           |# a  p   1    x         y        z        d        e        f   |
#| a   p  1  2  y    e|           |# b  o   1    w                           g                     |  
#| a   p  1  3  z    f|  ----->   |# b  o   2    v                           h                     | 
#| b   o  1  1  w    g|           |# b  o   3    s                           i                     |
#| b   o  2  1  v    h|           |# c  n   1    t         r                 j        k            |
#| b   o  3  1  s    i|           |# c  n   2    u                           l                     |
#| c   n  1  1  t    j|           |________________________________________________________________|
#| c   n  1  2  r    k|           
#| c   n  2  1  u    l|
#|____________________|

data = {'R' : ['a', 'a', 'a', 'b', 'b', 'b', 'c', 'c', 'c'], 
        'Rc': ['p', 'p', 'p', 'o', 'o', 'o', 'n', 'n', 'n'],
        'J' : [1, 1, 1, 1, 2, 3, 1, 1, 2], 
        'T' : [1, 2, 3, 1, 1, 1, 1, 2, 1], 
        'Ca': ['x', 'y', 'z', 'w', 'v', 's', 't', 'r', 'u'],
        'Cb': ['d', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l']}

df = pd.DataFrame(data=data)

Я не хочу потерять данные в R c, Ca или Cb.

R c (или каждый столбец, заканчивающийся на 'c') одинаков для каждого R, так что его можно просто сгруппировать с R.

Но Ca и Cb ( или каждый столбец, который начинается с 'C'), уникален для каждого T, который будет агрегирован и в противном случае потерян. Вместо этого их необходимо сохранить в новых столбцах с именем Ca (T = 1) для случаев, когда T = 1, Ca (T = 2) для случаев, когда T = 2, и Ca (T = 3) для случаев, когда T = 3. То же самое касается Cb.

Итак, используя T, мне нужно создать количество столбцов T для каждого Ca и Cb с учетом T, которое записывает данные из Ca и Cb в новые столбцы.

PS. Если это помогает, оба столбца J и T имеют дополнительный столбец с уникальными идентификаторами.

J_ID = [1,1,1,2,3,4,5,5,6]
T_ID = [1,2,3,4,5,6,7,8,9]

То, что я пробовал до сих пор:

(
    df.groupby(['R','J'])
    .apply(lambda x: x.Ca.tolist()).apply(pd.Series)
    .rename(columns=lambda x: f'Ca{x+1}')
    .reset_index()
)

Проблема: возможно выполнить только с одним из C и я теряю R c.

Любая помощь будет принята с благодарностью!

Ответы [ 2 ]

2 голосов
/ 20 апреля 2020

Вы можете использовать pivot_table ( здесь документы ) с лямбда-функцией в качестве аргумента aggfunc:

table = pd.pivot_table(df, index = ['R','Rc','J'],values = ['Ca','Cb'],
                    columns = ['T'], fill_value = '', aggfunc = lambda x: ''.join(str(v) for v in x)).reset_index()


   R Rc  J Ca       Cb      
T           1  2  3  1  2  3
0  a  p  1  x  y  z  d  e  f
1  b  o  1  w        g      
2  b  o  2  v        h      
3  b  o  3  s        i      
4  c  n  1  t  r     j  k   
5  c  n  2  u        l      

Затем вы можете удалить многоиндексные столбцы и переименовать следующим образом (взято из этого великого ответа ):

table.columns = ['%s%s' % (a, ' (T = %s)' % b if b else '') for a, b in table.columns]

   R Rc  J Ca (T = 1) Ca (T = 2) Ca (T = 3) Cb (T = 1) Cb (T = 2) Cb (T = 3)
0  a  p  1          x          y          z          d          e          f
1  b  o  1          w                                g                      
2  b  o  2          v                                h                      
3  b  o  3          s                                i                      
4  c  n  1          t          r                     j          k           
5  c  n  2          u                                l                      
0 голосов
/ 20 апреля 2020

Если я понимаю, что вам нужно, вы можете просто найти нужные строки следующим образом:

df['Ca(T=1)']=df['Ca'].loc[df['T']==1]

вы должны повторить это для разных T

...