2016-12-14 4 views
1

Предположим, у меня есть следующий файл .txt:Создать новый столбец для каждого совпадения символа строки в панд

Alabama[edit] 
fooAL 
barAL 
Arizona[edit] 
fooAz 
barAz 
bazAz 
Alaska[edit] 
fooAk 
... 

Как я могу преобразовать это в кадр панды данных формы

| St. Name | Region | 
|----------+--------| 
| Alabama | fooAL | 
| Alabama | barAL | 
| Arizona | fooAz | 
| Arizona | barAz | 
| Arizona | bazAz | 
| Alaska | fooAk | 
| ...  | ... | 

Так что я думал, что используется строка символов [edit], которая появляется после каждого имени состояния как sep= '\[edit\]' в качестве аргумента в read_csv в pandas. Но это не дает мне то, что я хочу.

Но я все еще думаю, что могу использовать какое-то регулярное выражение здесь, чтобы делать то, что хочу, не пишу для циклов или чего-то подобного. Не могли бы вы помочь?

+0

И это действительно выглядит очень много, как [неделя 4 Введение в науку данных в Python] (HTTPS : //www.coursera.org/learn/python-data-analysis) на coursera :) –

+0

Да, это так. Они советуют вам задавать вопросы о stackoverflow. Так я и сделал :) – minibuffer

ответ

1

Я предлагаю не полагаться на панд прямо здесь, но сделать в разборе, открыв файл и справиться с ним построчно составить список Dict, и использовать его для создания dataframe:

with open('yourfile.txt','r') as f: 
    content = f.read().splitlines() 

state = None 
l_dict = [] 
for line in content: 
    if '[edit]' in line: 
     state = line.split('[')[0] 
    else: 
     l_dict.append({'St. Name':state, 'Region':line}) 

df = pd.DataFrame(l_dict) 
df.set_index('St. Name', inplace=True) 

Если вы действительно хотите сделать в панд, я думаю, вы могли бы сделать это таким образом, путем обработки государств и регионов в отдельности, а также с использованием forward fill из NaNs (DataFrame.ffill такая же, как fillna(method='ffill') (или pad)

df = pd.DataFrame('yourfile.txt', columns=['txt']) 
# Create a column that'll serve as a filter IsState 
df['IsState'] = df['txt'].str.contains('\[edit\]') 

# Split and get first item of split 
df.loc[df.IsState, 'St. Name'] = df.loc[df.IsState, 'txt'].str.split('[').str.get(0) 

# the `~`means not 
df.loc[~df.IsState, 'Region'] = df.loc[~df.IsState, 'txt'] 

# Forward fill the NaNs 
df['St. Name'] = df['St. Name'].ffill() 

# Select what you truly want and set index 
df = df.loc[~df.IsState, ['St. Name', 'Region']] 
df.set_index('St. Name', inplace=True) 
3
# header is None and names=['St. Name'] 
s = pd.read_csv('yourfile.txt', header=None, squeeze=True, names=['St. Name']) 

# grab [edit] lines 
st = s.str.extract('(.*)\[edit\]').ffill() 
# groupby 
g = s.groupby(st) 
# use tail(-1) to get all but first row 
df = g.apply(pd.Series.tail, n=-1) 
# reset_index to get what we want 
df.reset_index('St. Name', name='Region') 

enter image description here


же в одной строке

s = pd.read_csv(StringIO(txt), header=None, squeeze=True, names=['St. Name']) 

s.groupby(s.str.extract('(.*)\[edit\]').ffill()) \ 
    .apply(pd.Series.tail, n=-1) \ 
    .reset_index('St. Name', name='Region') 
+0

Me likey! Очень элегантно. –

Смежные вопросы