熊猫wide_to_long-在i中保留值所在的行,或在空白处保留一行

时间:2019-05-29 15:04:11

标签: python pandas

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

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

换句话说,对于每个id,我至少要保留一条记录: -如果ID在存根中没有数据,则为一条记录, -或存根中填充了id的行

我之所以使用wide_to_long是因为它允许使用stubnames不允许的melt(或者至少我不知道该如何使用)。这是示例代码(受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   

我需要实现的目标: 对于ID 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列均为空的行,但仍然为每个id保留至少1条记录(如果A和B都为空白,则保留一条记录)

3 个答案:

答案 0 :(得分:3)

遵循您的条件和逻辑

UPDATE table1
SET table1.value1 = (SELECT value1
                     FROM table2
                     WHERE ((table1.value1 IS NULL)
                       AND  (table1.[key] = table2.[key]))),

    table1.datevalue = (SELECT datevalue
                        FROM table2
                        WHERE ((table1.[key] = table2.[key])
                          AND  (table1.value1 IS NULL)))

答案 1 :(得分:2)

在使用阈值wide_to_long然后dropna之前,先屏蔽为NaN。

m检查是否每个存根列都为空。根据{{​​1}},以NaN代替''的全部或除一个以外的所有m。这样,当所有存根都丢失时,我们可以在结果中仅保留一行:

如果您在suffix中更改了sepwide_to_long参数,则需要相应地调整scols的创建。

stubs = ['A', 'B']
scols = df.columns[df.columns.str.split('[0-9]+').str[0].isin(stubs)]  #Mimic stubs
m = df.loc[:, scols].eq('').all(1)

df.loc[~m, scols] = df.loc[~m, scols].replace('', np.NaN)
df.loc[m, scols[1:]] = np.NaN

(pd.wide_to_long(df.assign(id=df.index), stubnames=stubs, i="id", j="year")
   .dropna(thresh=1)
   .replace(np.NaN, '')  #Or perhaps the empty to NaN
)

输出:

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

答案 2 :(得分:1)

类似于WeNYoBen

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

def f(d):
    m = d.A.eq('')
    return d.head(1) if m.all() else d[~m]

t = pd.concat([f(d) for _, d in s.groupby('id')])

t.loc[[*filter(t.index.__contains__, s.index)]]

         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