Python: сводная таблица / группа по определенным условиям - PullRequest
0 голосов
/ 11 марта 2019

Я пытаюсь изменить структуру моих данных из текстового файла (.txt), данные которого выглядят так:

:1:A
:2:B
:3:C
:1:D
:2:E
:3:F
:4:G
:1:H
:3:I
:4:J

И я хотел бы преобразовать их в этот формат (например, сводную таблицу).В Excel, какое имя столбца является символом между ":", и каждая группа всегда начинается с: 1:)

Group   :1: :2: :3: :4:
1        A   B   C
2        D   E   F   G
3        H       I   J

У кого-нибудь есть идеи?Заранее спасибо.

Ответы [ 3 ]

1 голос
/ 11 марта 2019

Сначала создайте DataFrame с помощью read_csv с header=None, потому что в файле нет заголовка:

import pandas as pd

temp=u""":1:A
:2:B
:3:C
:1:D
:2:E
:3:F
:4:G
:1:H
:3:I
:4:J"""
#after testing replace 'pd.compat.StringIO(temp)' to 'filename.csv'
df = pd.read_csv(pd.compat.StringIO(temp), header=None)
print (df)
      0
0  :1:A
1  :2:B
2  :3:C
3  :1:D
4  :2:E
5  :3:F
6  :4:G
7  :1:H
8  :3:I
9  :4:J

Извлеките исходный столбец с помощью DataFrame.pop, затем удалите значения : с помощью Series.str.strip и Series.str.split значений для 2 новых столбцов. Затем создайте группы, сравнив их с Series.eq для == по строке 0 с Series.cumsum, создайте MultiIndex с помощью DataFrame.set_index и последним изменением формы Series.unstack:

df[['a','b']] = df.pop(0).str.strip(':').str.split(':', expand=True)
df1 = df.set_index([df['a'].eq('1').cumsum(), 'a'])['b'].unstack(fill_value='')
print (df1)
a  1  2  3  4
a            
1  A  B  C   
2  D  E  F  G
3  H     I  J
0 голосов
/ 11 марта 2019

Еще один способ сделать это:

#read the file
with open("t.txt") as f:
    content = f.readlines()
#Create a dictionary and read each line from file to keep the column names (ex, :1:) as keys and rows(ex, A) as values in dictionary.
my_dict={}
for v in content:
    key = v.rstrip(':')[0:3] # take the value ':1:'
    value = v.rstrip(':')[3] # take value 'A'
    my_dict.setdefault(key,[]).append(value) 
#convert dictionary to dataframe and transpose it
df = pd.DataFrame.from_dict(my_dict,orient='index').transpose()
df

Вывод будет выглядеть так:

   :1: :2: :3: :4:
0   A   B   C   G
1   D   E   F   J
2   H  None I  None
0 голосов
/ 11 марта 2019

Использование:

# Reading text file (assuming stored in CSV format, you can also use pd.read_fwf)
df = pd.read_csv('SO.csv', header=None)

# Splitting data into two columns
ndf = df.iloc[:, 0].str.split(':', expand=True).iloc[:, 1:]

# Grouping and creating a dataframe. Later dropping NaNs
res = ndf.groupby(1)[2].apply(pd.DataFrame).apply(lambda x: pd.Series(x.dropna().values))

# Post processing (optional)
res.columns = [':' + ndf[1].unique()[i] + ':' for i in range(ndf[1].nunique())]
res.index.name = 'Group'
res.index = range(1, res.shape[0] + 1)
res

Group   :1: :2: :3: :4:
1        A   B   C
2        D   E   F   G
3        H       I   J
...