Python Pandas dataframe - объединение / объединение строк с пустыми значениями - PullRequest
1 голос
/ 20 апреля 2020

У меня есть следующий фрейм данных df (просто образец с 6 строками):

df = pd.DataFrame({'#': [1, 1, 2, 3, 3, 3],
                   'Name': ['john', 'john', 'max', 'tim', 'tim', 'tim'],
                   'Phone': ['01234', '98765', '', '', '33445566', ''],
                   'ID': ['', '', '11111', '2222222', '', ''],
                   'User': ['', '', '', '', '', 'tim123']})

print (df)

      #  Name     Phone       ID       User
0     1  john     01234                 
1     1  john     98765                 
2     2   max                 11111        
3     3   tim                 2222222        
4     3   tim     33445566                 
5     3   tim                          tim123

Теперь я хочу объединить все записи, такие как # 3 (Тим). Мой желаемый фрейм данных должен выглядеть следующим образом:

   #  Name     Phone       ID        User
0  1  john     01234              
1  1  john     98765              
2  2   max                 11111     
3  3   tim     33445566    2222222   tim123  

Поэтому я хочу объединить столбцы «Телефон», «Идентификатор» и «Пользователь» для строк с одним и тем же символом # и столбцом имени в фрейме данных. , У вас есть какие-нибудь полезные предложения, как я могу это сделать?

Заранее большое спасибо!

1 Ответ

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

Используйте justify функцию для каждой группы, а затем удаляйте только пустые строки:

#https://stackoverflow.com/a/44559180/2901002
def justify(a, invalid_val=0, axis=1, side='left'):    
    """
    Justifies a 2D array

    Parameters
    ----------
    A : ndarray
        Input array to be justified
    axis : int
        Axis along which justification is to be made
    side : str
        Direction of justification. It could be 'left', 'right', 'up', 'down'
        It should be 'left' or 'right' for axis=1 and 'up' or 'down' for axis=0.

    """

    if invalid_val is np.nan:
        mask = pd.notna(a)
    else:
        mask = a!=invalid_val
    justified_mask = np.sort(mask,axis=axis)
    if (side=='up') | (side=='left'):
        justified_mask = np.flip(justified_mask,axis=axis)
    out = np.full(a.shape, invalid_val, dtype=object) 
    if axis==1:
        out[justified_mask] = a[mask]
    else:
        out.T[justified_mask.T] = a.T[mask.T]
    return out

f = lambda x: pd.DataFrame(justify(x.values,invalid_val='', side='up', axis=0),
                           columns=df.columns[2:])
df = df.set_index(['#','Name']).groupby(level=[0,1]).apply(f)
df = df[df.ne('').any(axis=1)].reset_index(level=2, drop=True).reset_index()
print (df)
   #  Name     Phone       ID    User
0  1  john     01234                 
1  1  john     98765                 
2  2   max              11111        
3  3   tim  33445566  2222222  tim123
...