我正在尝试将数据框转换为长格式,并希望遵循以下规则保存记录:
(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都为空白,则保留一条记录)
答案 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
中更改了sep
或wide_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)
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