首页 > 解决方案 > Pandas wide_to_long - 将值保留在 i 中的行或仅保留一行空白

问题描述

我正在尝试将数据框转换为长格式,并希望按照以下规则保留记录:

(1) 如果 id 在存根中有数据 - 保留所有非空的“长”记录,删除空的 (2) 如果 id 在任何存根中没有数据,只保留 1 条“长”记录它的

换句话说,对于每个id我需要保留至少一条记录:-如果 id 在存根中没有数据,则恰好是一条记录,-或者与id存根中填充的行数一样多

我正在使用wide_to_long,因为它允许使用stubnames,而melt不允许使用(或者至少我不知道如何使用)。这是示例代码(受官方 pandas 文档的启发wide_to_long):

import numpy as np
import pandas as pd

np.random.seed(123)
df = pd.DataFrame({"A2001" : {0 : "a", 1 : "b", 2 : "c",3:""},
                    "A2002" : {0 : "d", 1 : "e", 2 : "",3:""},
                    "A2003" : {0 : "g", 1 : "h", 2 : "i",3:""},
                    "A2004" : {0 : "j", 1 : "k", 2 : "l",3:""},
                   })

df["id"] = df.index
pd.wide_to_long(df, ["A"], i="id", j="year")

输出是:

         A
id year   
0  2001  a
1  2001  b
2  2001  c
3  2001   
0  2002  d
1  2002  e
2  2002   
3  2002   
0  2003  g
1  2003  h
2  2003  i
3  2003   
0  2004  j
1  2004  k
2  2004  l
3  2004   

我需要实现的目标:对于 ids 0、1 和 2,我需要["A"]空白的行(或NaN);对于 id 3 - 我需要保留 1 行(任何一行,不管哪一行):

         A
id year   
0  2001  a
1  2001  b
2  2001  c
3  2001   
0  2002  d
1  2002  e
0  2003  g
1  2003  h
2  2003  i
0  2004  j
1  2004  k
2  2004  l

我试过这个:

df.dropna(axis=0,how="all",subset=["A"]) 

但它会删除 id 3 的所有行

编辑:

我也在寻找一个通用的解决方案,其中包含一个存根名称列表:

df = pd.DataFrame({"A2001" : {0 : "a", 1 : "b", 2 : "",3:""},
                    "A2002" : {0 : "d", 1 : "e", 2 : "test",3:""},
                    "A2003" : {0 : "g", 1 : "h", 2 : "i",3:""},
                    "A2004" : {0 : "j", 1 : "k", 2 : "l",3:""},
                    "B2001" : {0 : "a", 1 : "b", 2 : "",3:""},
                    "B2002" : {0 : "d", 1 : "e", 2 : "",3:""},
                    "B2003" : {0 : "g", 1 : "h", 2 : "i",3:""},
                    "B2004" : {0 : "j", 1 : "k", 2 : "l",3:""},
                   })

pd.wide_to_long(df, ["A","B"], i="id", j="year")

我需要删除 A 列和 B 列都为空的行,但仍为每列保留至少 1 条记录id(如果 A 和 B 均为空白,则仅保留一条记录)

标签: pythonpandas

解决方案


遵循你的条件和逻辑

df["id"] = df.index
s=pd.wide_to_long(df, ["A"], i="id", j="year")
s=s.groupby(level=0).A.apply(lambda x : x.head(1) if (x=='').all() else x[x!='']).reset_index(level=0,drop=True)
s.sort_index(level=1)

Out[137]: 
id  year
0   2001    a
1   2001    b
2   2001    c
3   2001     
0   2002    d
1   2002    e
0   2003    g
1   2003    h
2   2003    i
0   2004    j
1   2004    k
2   2004    l
Name: A, dtype: object

推荐阅读