объединение пустых строк во фрейме данных - PullRequest
0 голосов
/ 06 марта 2020

У меня есть фрейм данных, как показано ниже

Name         ID         Rank
==============================
Jobn        0001        1
Wick        Nan         Nan
John        0101        22
lewis       Nan         Nan
James       0201        12
Bo          Nan         Nan
nd          Nan         Nan

Здесь мне нужно объединить имена на основе значений идентификатора и ранга, если его Nan, то мне нужно объединить имена в разных строках, пока значения не будут не Nan.

Вывод выглядит следующим образом

Name         ID         Rank
==============================
Jobn Wick       0001        1
John lewis      0101        22
James Bo nd     0201        12

Я попробовал следующий код

for rowid in range(len(tableDf)):
    for colid in  range(len(tableDf.columns)):
        if pd.isna(tableDf.iloc[rowid,colid]):
            print(tableDf.iloc[rowid-1,colid])
            #print(type(tableDf.iloc[rowid - 1, colid]))
            if type(tableDf.iloc[rowid - 1, colid]) == str:
                print("got a string nan")
                # tableDf.at[rowid-1,colid] = str(tableDf.iloc[rowid-1,colid]) +   str(tableDf.iloc[rowid,colid])
            else:
                print("got a NON string nan")
                # tableDf.at[rowid - 1, colid] = tableDf.iloc[rowid - 1, colid] + tableDf.iloc[rowid, colid]

Но я не могу объединить строки. Любые предложения, как Для решения этой проблемы? Примечание. Имена столбцов не являются фиксированными. Может измениться.

Ответы [ 2 ]

1 голос
/ 06 марта 2020

IIU C, GroupBy.agg

#df = df.mask(df.eq('Nan'))   #if neccesary
blocks = df[['ID', 'Rank']].notna().all(axis=1).cumsum()
new_df = (df.groupby(blocks, as_index=False)
            .agg({'Name' : ' '.join,
                  'ID' : 'first',
                  'Rank': 'first'}))
print(new_df)

Выход

          Name    ID Rank
0    Jobn Wick  0001    1
1   John lewis  0101   22
2  James Bo nd  0201   12

Деталь

print(blocks)
0    1
1    1
2    2
3    2
4    3
5    3
6    3
dtype: int64

РЕДАКТИРОВАТЬ

, если у вас есть столбец Имя и многие другие:

cols = df.columns.difference(['Name'])
blocks = df[cols].notna().all(axis=1).cumsum()
new_df = (df.groupby(blocks, as_index=False)
            .agg(dict({'Name': ' '.join}, **dict(zip(cols, ['first']*len(cols))))))
print(new_df)
          Name    ID Rank
0    Jobn Wick  0001    1
1   John lewis  0101   22
2  James Bo nd  0201   12

Или вы можете использовать:

cols = df.columns[1:]
blocks = df[cols].notna().all(axis=1).cumsum()
new_df = (df.groupby(blocks, as_index=False)
            .agg(dict({df.columns[0]: ' '.join}, **dict(zip(cols, ['first']*len(cols))))))
print(new_df)
          Name    ID Rank
0    Jobn Wick  0001    1
1   John lewis  0101   22
2  James Bo nd  0201   12
1 голос
/ 06 марта 2020

Вот как я это сделал:

df['ID'].fillna(method='ffill',inplace=True)
name_dict = {i:' '.join(df['Name'].loc[df['ID']==i].values) for i in df['ID'].unique()}
df['Name'] = df['ID'].apply(lambda x: name_dict[x])
df.dropna(axis=0,inplace=True)

Вместо того, чтобы объединять строки, вы можете воспользоваться тем, что только одна строка на идентификатор имеет ненулевые значения. Затем вы можете сделать это вперед, заполнив столбец идентификаторов, чтобы скрипт знал, какие строки ассоциировать с какими идентификаторами. Затем вы отображаете имена обратно на все строки с идентификаторами. Теперь у вас будет много строк с повторяющимися именами, но только одна строка на имя не будет иметь нулевого значения для ранга, поэтому вы можете отбросить любые строки, имеющие нулевые значения в столбце.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...