我有一个数据框,可以从下面给出的代码中生成
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列以上。我的真实数据不是subject_id,而是我的真实数据,它的subject_ID是DC0001,DC0002等值。“ I”是否总是必须为数字?相反,它将存根值添加为数据集中的新列,并且行数为零
这就是我的真实专栏的样子
我的真实数据也可能包含NA。那么,是否必须使用默认值填充它们才能使wide_to_long工作?
请问您能解决什么问题?或任何其他获得相同结果的方法也很有帮助。
答案 0 :(得分:0)
问题出在您的列名上,用于从宽到长转换的数字必须在列名的末尾,或者您需要为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
答案 1 :(得分:0)
尝试在允许字符串后缀的函数中添加其他参数。
pd.long_to_wide(.......................,suffix='\w+')