Как разбить столбцы DataFrame на несколько строк? - PullRequest
0 голосов
/ 21 октября 2019

Я пытаюсь преобразовать несколько столбцов в несколько строк. Может кто-нибудь предложить какой-нибудь совет?

У меня есть DataFrame:

id .        values
1,2,3,4     [('a','b'), ('as','bd'),'|',('ss','dd'), ('ws','ee'),'|',('rr','rt'), ('tt','yy'),'|',('yu','uu'), ('ii','oo')]

Мне нужно, чтобы он выглядел так:

ID       Values
1         ('a','b'), ('as','bd')
2         ('ss','dd'), ('ws','ee')
3         ('rr','rt'), ('tt','yy')
4         ('yu','uu'), ('ii','oo')

Я пробовал groupby,split, izip. Может я не правильно делаю?

Ответы [ 2 ]

0 голосов
/ 22 октября 2019

Я придумал довольно краткое решение, основанное на многоуровневой группировке, которая, по моему мнению, в значительной степени pandasonic .

Начнем с определения следующей функции: "разбиение "a Series , взятых из отдельных значений элемента на последовательность представлений списков, без окружающих [ и ] . Разделение происходит в каждом элементе '|' .:

def fn(grp1):
    grp2 = (grp1 == '|').cumsum()
    return grp1[grp1 != '|'].groupby(grp2).apply(lambda x: repr(list(x))[1:-1])

(будет использовано чуть позже).

Первый шаг обработки - преобразование id столбец в Series :

sId = df.id.apply(lambda x: pd.Series(x.split(','))).stack().rename('ID')

Для ваших данных результат:

0  0    1
   1    2
   2    3
   3    4
Name: ID, dtype: object

Первый уровень MultiIndex - индексстроки-источника и второго уровня являются последовательными числами (в пределах текущей строки).

Теперь пришло время выполнить аналогичное преобразование столбца значений :

sVal = pd.DataFrame(df['values'].values.tolist(), index= df.index)\
    .stack().groupby(level=0).apply(fn).rename('Values')

Результат:

0  0      ('a', 'b'), ('as', 'bd')
   1    ('ss', 'dd'), ('ws', 'ee')
   2    ('rr', 'rt'), ('tt', 'yy')
   3    ('yu', 'uu'), ('ii', 'oo')
Name: Values, dtype: object

Обратите внимание, что вышеприведенный MultiIndex имеет ту же структуру, что и в случае sId .

И последний шаг - concat оба эти частичных результата:

result = pd.concat([sId, sVal], axis=1).reset_index(drop=True)

Результат:

  ID                      Values
0  1    ('a', 'b'), ('as', 'bd')
1  2  ('ss', 'dd'), ('ws', 'ee')
2  3  ('rr', 'rt'), ('tt', 'yy')
3  4  ('yu', 'uu'), ('ii', 'oo')
0 голосов
/ 21 октября 2019

Я сделал быстрый и грязный пример, как вы можете разобрать этот фрейм данных

# example dataframe
df = [
    "1,2,3,4",
    [('a','b'), ('as','bd'), '|', ('ss','dd'), ('ws','ee'), '|', ('rr','rt'), ('tt','yy'), '|', ('yu','uu'), ('ii','oo')]
]

# split ids by comma
ids = df[0].split(",")

# init Id and Items as int and dict()
Id = 0
Items = dict()

# prepare array for data insert
for i in ids:
    Items[i] = []

# insert data
for i in df[1]:
    if isinstance(i, (tuple)):
        Items[ids[Id]].append(i)
    elif isinstance(i, (str)):
        Id += 1

# print data as written in stackoverflow question
print("id .\tvalues")
for item in Items:
    print("{}\t{}".format(item, Items[item]))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...