首页 > 解决方案 > 基于输入行的 pandas long_to_wide 方法

问题描述

我在删除空值时遇到问题。我的输入数据框

name    no     city     tr1_0  tr2_0    tr3_0     tr1_1  tr2_1      tr3_1   tr1_2   tr2_2   tr3_2 
John    11     edi      boa    51        110      cof      52       220   
Rick    12     new      cof    61        100      dcu      61       750   
Mat     t1     nyc

我想要的输出

     name    no city  tr1  tr3  tr2   
0    John    11  edi  boa  110   51  
1    John    11  edi  cof  220   52    
2    Rick    12  new  cof  100   61   
3    Rick    12  new  dcu  750   61  
4    Matt    13  wil  nan  nan  nan

我用下面的代码

df1 = pd.read_fwf(inputFileName, widths=widths, names=names, dtype=str, index_col=False )

feature_models = [col for col in df1.columns if re.match("tr[0-9]_[0-9]",col) is not None]

features = list(set([ re.sub("_[0-9]","",feature_model) for feature_model in feature_models]))
ub("_[0-9]","",feature_model) for feature_model in feature_models]))

df1 = pd.wide_to_long(df1,i=['name', 'no', 
df1 = pd.wide_to_long(df1,i=['name', 'no', 'city',],j='ModelID',stubnames=features,sep="_")

我当前的输出如下。第 2 行在我的用例中没有任何意义,所以我根本不想生成该行。如果没有拖车,我只想要 1 行,这很好(第 6 行)。如果有 2 个拖车,我只想要 2 行,但它给了我 3 行。(第 2 行和第 5 行是额外的)。我尝试使用 dropna 但它不起作用。同样在我的情况下,它的打印为 nan 而不是 NaN。

     name    no city  tr1  tr3  tr2 
0    John    11  edi  boa  110   51 .  
1    John    11  edi  cof  220   52 .  
2    John    11  edi  nan  nan  nan .  
3    Rick    12  new  cof  100   61 .  
4    Rick    12  new  dcu  750   61 .  
5    Rick    12  new  nan  nan  nan .  
6    Matt    13  wil  nan  nan  nan .  

标签: pythonpandas

解决方案


您可以将此替代解决方案与splitand一起使用stack

df1 = df1.set_index(['name', 'no', 'city'])
df1.columns = df1.columns.str.split('_', expand=True)
df1 = df1.stack(1, dropna=False).reset_index(level=3, drop=True)

mask = df1.index.duplicated() & df1.isnull().all(axis=1)

df1 = df1[~mask].reset_index()
print (df1)
   name  no city  tr1   tr2    tr3
0  John  11  edi  boa  51.0  110.0
1  John  11  edi  cof  52.0  220.0
2  Rick  12  new  cof  61.0  100.0
3  Rick  12  new  dcu  61.0  750.0
4   Mat  t1  nyc  NaN   NaN    NaN

使用您的解决方案:

df1 = pd.wide_to_long(df1,i=['name', 'no', 'city'],j='ModelID',stubnames=features,sep="_")

对于删除NaN具有重复MultiIndex值的 s,可以使用以下过滤boolean indexing

#remove counting level
df1 = df1.reset_index(level=3, drop=True)
mask = df1.index.duplicated() & df1.isnull().all(axis=1)
df1 = df1[~mask].reset_index()

详情

通过以下方式检查受骗者Index.duplicated

print (df1.index.duplicated())
[False  True False  True False  True]

DataFrame.all然后通过for 检查True每行的所有 s检查缺失值:

print (df1.isnull().all(axis=1))
name  no  city
John  11  edi     False
          edi     False
Rick  12  new     False
          new     False
Mat   t1  nyc      True
          nyc      True
dtype: bool

通过&for链接bitwise AND

mask = df1.index.duplicated() & df1.isnull().all(axis=1)
print (mask)
name  no  city
John  11  edi     False
          edi     False
Rick  12  new     False
          new     False
Mat   t1  nyc     False
          nyc      True
dtype: bool

反转布尔掩码~

print (~mask)
name  no  city
John  11  edi      True
          edi      True
Rick  12  new      True
          new      True
Mat   t1  nyc      True
          nyc     False
dtype: bool

推荐阅读