2016-08-30 2 views
1

Я пытаюсь разделить и слить кадр данных Pandas.Split and merge pandas dataframe

Столбцы исходного кадра данных расположены так:

dataTime Record1Field1 ... Record1FieldN Record2Field1 ... Record1FieldN 
time1 <<  record 1 data   >> <<  record 2 data  >> 

Я хотел бы взять расколоть Record2 поля в отдельный фрейм данных tempdf, индексированные по dataTime. Поэтому tempdf будет выглядеть примерно так:

dataTime Record2Field1 ... Record2FieldN 
time1 << record 2 data    >> 

После tempdf заполняется, удалите столбцы Record2 из исходного кадра данных. Первая трудность, с которой я столкнулся, заключается в создании этого tempdf, который содержит данные записи 2.

Затем я хотел бы переименовать столбцы в tempdf, чтобы они совпадали с столбцами Record1 в исходном фрейме данных. (Эта часть, которую я знаю, как это сделать)

Наконец-то я хотел бы объединить tempdf обратно в исходный фрейм данных.

Конечный результат должен выглядеть примерно так:

dataTime Record1Field1 ... Record1FieldN 
time1 <<record 1 data>> 
time1 <<record 2 data>> 

До сих пор я не определил хороший способ сделать это. Любая помощь приветствуется! Благодарю.

+0

Правильно ли я, что у вас есть только, чтобы сделать [ 'merge'] (http://pandas.pydata.org/pandas-docs/stable/generated/pandas .DataFrame.merge.html)? – ragesz

+0

использовать 'concat' или' append' – lowtech

+0

@ragesz Извините, я неверно отреагировал. Нет, часть проблемы, которую я имею, заключается в создании фрейма данных tempdf, который содержит все данные записи 2. – dgikmo

ответ

0

Вы можете получить все ваши Record2 значения под Record1 столбцов следующим образом:

Установка данных:

data = StringIO(
''' 
dataTime Record1Field1 Record1Field2 Record1Field3 Record2Field1 Record2Field2 Record2Field3 
01-01-2015 1 2 3 4 5 6 
''') 

df = pd.read_csv(data, delim_whitespace=True, parse_dates=['dataTime']) 
print (df) 

    dataTime Record1Field1 Record1Field2 Record1Field3 Record2Field1 \ 
0 2015-01-01    1    2    3    4 

    Record2Field2 Record2Field3 
0    5    6 

Операции:

df.set_index('dataTime', inplace=True) 

# Filter column names corresponding to Record2 
tempdf = df[[col for col in list(df) if col.startswith('Record2')]] 

# Drop those columns after assigning to tempdf 
df.drop(tempdf.columns, inplace=True, axis=1) 

# Rename the column names for appending 
tempdf.columns = [col for col in list(df) if col.startswith('Record1')] 

# Concatenate row-wise 
print (df.append(tempdf)) 

      Record1Field1 Record1Field2 Record1Field3 
dataTime            
2015-01-01    1    2    3 
2015-01-01    4    5    6 
+1

Это сделало это! Я закончил использование фильтра регулярных выражений, как в ответе, предоставленном @unutbu. Спасибо за вашу помощь! – dgikmo

0

попробуйте использовать concat

Так что пытается что-то вроде:

Combined = [DataFrame1,DataFrame2] 
Together = pandas.concat(Combined) 

как один из других комментированные - merge может быть хорошим вариантом, как хорошо.

+0

Hi Matt. Спасибо за ваш ответ. Я понял, что не задал вопрос, который мне больше всего нужен, и как создать «tempdf». Я отредактировал свой пост, чтобы более четко объяснить проблемы, которые у меня есть. – dgikmo

+0

Будет ли это статическим решением? или вы будете внедрять этот код в разные кадры данных? Прошу, потому что вы можете «жестко закодировать» удаление ненужных столбцов для одноразового решения. Теперь, на ваш вопрос, 'tempdf' исходит из части исходного фрейма? это верно? – MattR

+0

Это действительно будет статическое решение. Кроме того, да, tempdf будет полностью заполнен из исходного фрейма. – dgikmo

0

, если вы знаете, столбцы, которые будут выбраны, а затем использовать

tempdf = df[['a','b']] 

еще выбрать последние 2 колонки использовать

tempdf = df[df.columns[-2:]] 
0

Чтобы ответить на ваш непосредственный вопрос, вы можете использовать df.filter с рисунком регулярных выражений для выбора колонок в форме Record2FieldN:

In [29]: tempdf = df.filter(regex=r'Record2.*'); tempdf 
Out[29]: 
    Record2Field0 Record2Field1 Record2Field2 
0    3    8    4 
1    2    6    3 
2    1    2    2 
3    5    9    4 

, и вы можете переименовать столбцы с помощью tempdf.rename:

tempdf = tempdf.rename(columns={'Record2Field{}'.format(i):'Record1Field{}'.format(i) for i in range(3)}) 

и drop в Record2 полей из df с:

df = df.drop(['Record2Field{}'.format(i) for i in range(3)], axis=1) 

Но есть лучший подход к вашим общим проблемам: Заменить квартиру названия колонок RecordMFieldN с 2-уровневым MultiIndex, который разбивает Record на Field. Это даст вам достаточно контроля, чтобы стека данных в желаемой форме:

import numpy as np 
import pandas as pd 
np.random.seed(2016) 

ncols, nrows = 3, 4 
def make_dataframe(ncols, nrows): 
    columns = ['Record{}Field{}'.format(i, j) for i in range(1,3) 
       for j in range(ncols)] 
    df = pd.DataFrame(np.random.randint(10, size=(nrows, 2*ncols)), columns=columns) 
    df['dataTime'] = pd.date_range('2000-1-1', periods=nrows) 
    return df 

df = make_dataframe(ncols, nrows) 

# stash the `dataTime` in the row index so we can reassign 
# the column index to `new_index` 
result = df.set_index('dataTime') 
new_index = pd.MultiIndex.from_product([[1,2], df.columns[:ncols]], 
             names=['record', 'field']) 
result.columns = new_index 

# Now the problem can be solved by stacking. 
result = result.stack('record') 
result.index = result.index.droplevel('record') 

дает

field  Record1Field0 Record1Field1 Record1Field2 
dataTime            
2000-01-01    3    7    2 
2000-01-01    3    8    4 
2000-01-02    8    7    9 
2000-01-02    2    6    3 
2000-01-03    4    1    9 
2000-01-03    1    2    2 
2000-01-04    8    9    8 
2000-01-04    5    9    4