Широкий на длинный возвращает пустой вывод - Python dataframe - PullRequest
1 голос
/ 28 июня 2019

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

df = pd.DataFrame({'person_id' :[1,2,3],'date1': 
['12/31/2007','11/25/2009','10/06/2005'],'val1': 
[2,4,6],'date2': ['12/31/2017','11/25/2019','10/06/2015'],'val2':[1,3,5],'date3': 
['12/31/2027','11/25/2029','10/06/2025'],'val3':[7,9,11]})

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

pd.wide_to_long(df, stubnames=['date', 'val'], i='person_id', 
j='grp').sort_index(level=0)

Хотя это работает с примерами данных, как показано ниже, это не работает с моими реальными данными, которые имеют более 200 столбцов. Вместо person_id мои реальные данные имеют subject_ID, который представляет собой значения типа DC0001, DC0002 и т. Д. Всегда ли «I» должно быть числовым? Вместо этого он добавляет значения заглушки как новые столбцы в моем наборе данных и имеет нулевые строки

Вот так выглядят мои настоящие колонки

enter image description here

Мои реальные данные также могут содержать NA. Так нужно ли мне заполнять их значениями по умолчанию для работы wide_to_long?

enter image description here

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

1 Ответ

0 голосов
/ 28 июня 2019

Проблема связана с именами ваших столбцов, числа, используемые для преобразования из широких в длинные, должны быть в конце имен столбцов, или вам необходимо указать суффикс для groupby.Я думаю, что самое простое решение - создать функцию, которая принимает регулярные выражения и фрейм данных.

import pandas as pd
import re

def change_names(df, regex):
    # Select one of three column groups
    old_cols = df.filter(regex = regex).columns
    # Create list of new column names
    new_cols = []
    for col in old_cols:
        # Get the stubname of the original column
        stub = ''.join(re.split(r'\d', col))
        # Get the time point
        num = re.findall(r'\d+', col) # returns a list like ['1']
        # Make new column name
        new_col = stub + num[0]
        new_cols.append(new_col)

    # Create dictionary mapping old column names to new column names
    dd = {oc: nc for oc, nc in zip(old_cols, new_cols)}
    # Rename columns
    df.rename(columns = dd, inplace = True)

    return df


tdf = pd.DataFrame({'person_id' :[1,2,3],'h1date': ['12/31/2007','11/25/2009','10/06/2005'],'t1val': [2,4,6],'h2date': ['12/31/2017','11/25/2019','10/06/2015'],'t2val':[1,3,5],'h3date': ['12/31/2027','11/25/2029','10/06/2025'],'t3val':[7,9,11]})

# Change date columns
tdf = change_names(tdf, 'date$')
tdf = change_names(tdf, 'val$')

print(tdf)
    person_id      hdate1  tval1      hdate2  tval2      hdate3  tval3
0          1  12/31/2007      2  12/31/2017      1  12/31/2027      7
1          2  11/25/2009      4  11/25/2019      3  11/25/2029      9
2          3  10/06/2005      6  10/06/2015      5  10/06/2025     11
...