Pandas 在更宽的数据框中转换虚拟变量列表
Pandas converting list of variable in dummies in a wider dataframe
我导入了一个 json 文件,现在我有一个数据框,其中一列(代码)是一个列表。
index year gvkey code
0 1998 15686 ['TAX', 'ENVR', 'HEALTH']
1 2005 15372 ['EDUC', 'TAX', 'HEALTH', 'JUST']
2 2001 27486 ['LAB', 'TAX', 'HEALTH']
3 2008 84967 ['HEALTH','LAB', 'JUST']
我想得到的是:
index year gvkey TAX ENVR HEALTH EDUC JUST LAB
0 1998 15686 1 1 1 0 0 0
1 2005 15372 1 0 1 0 1 0
2 2001 27486 1 0 1 0 1 0
3 2008 84967 0 0 1 0 1 1
在 之后,我尝试了以下代码(其中 df 是我的数据框):
s = pd.Series(df["code"])
l = pd.get_dummies(s.apply(pd.Series).stack()).sum(level=0)
我得到了数据的第二部分(变量 TAX、ENVR、HEALTH、EDUC、JUST 和 LAB),但丢失了第一部分(年份和 gvkey)。
如何保留年份和 gvkey 变量?
我认为更好的解决方案是使用 DataFrame.pop
with Series.str.join
and Series.str.get_dummies
:
df = df.join(df.pop('code').str.join('|').str.get_dummies())
print (df)
year gvkey EDUC ENVR HEALTH JUST LAB TAX
index
0 1998 15686 0 1 1 0 0 1
1 2005 15372 1 0 1 1 0 1
2 2001 27486 0 0 1 0 1 1
3 2008 84967 0 0 1 1 1 0
如果性能很重要,请使用 MultiLabelBinarizer
:
from sklearn.preprocessing import MultiLabelBinarizer
mlb = MultiLabelBinarizer()
df1 = pd.DataFrame(mlb.fit_transform(df.pop('code')),columns=mlb.classes_)
df = df.join(df1)
print (df)
year gvkey EDUC ENVR HEALTH JUST LAB TAX
index
0 1998 15686 0 1 1 0 0 1
1 2005 15372 1 0 1 1 0 1
2 2001 27486 0 0 1 0 1 1
3 2008 84967 0 0 1 1 1 0
您的解决方案是可行的,,所以最好避免它,而且 sum
仅适用于唯一值,对于一般解决方案需要 max
:
df = df.join(pd.get_dummies(df.pop('code').apply(pd.Series).stack()).max(level=0))
print (df)
year gvkey EDUC ENVR HEALTH JUST LAB TAX
index
0 1998 15686 0 1 1 0 0 1
1 2005 15372 1 0 1 1 0 1
2 2001 27486 0 0 1 0 1 1
3 2008 84967 0 0 1 1 1 0
您可以通过以下方法完成此操作:
方法 1:将列转换为数据框并获取 dummies ,然后 groupby
on axis=1
并获取 max:
m = pd.get_dummies(pd.DataFrame(df['code'].tolist())).groupby(lambda x:
x.split('_')[1],axis=1).max()
final1 = df.drop('code',1).assign(**m)
方法 2:使用 |
加入列列表并使用 series.str.get_dummies
final2 = df.drop('code',1).assign(**df['code'].str.join('|').str.get_dummies())
方法 3:您的方法与 concat
s = pd.Series(df["code"])
l = pd.get_dummies(s.apply(pd.Series).stack()).max(level=0)
final3 = pd.concat((df.drop('code',1),l),axis=1)
#or final = df.drop('code',1).assign(**l)
我导入了一个 json 文件,现在我有一个数据框,其中一列(代码)是一个列表。
index year gvkey code
0 1998 15686 ['TAX', 'ENVR', 'HEALTH']
1 2005 15372 ['EDUC', 'TAX', 'HEALTH', 'JUST']
2 2001 27486 ['LAB', 'TAX', 'HEALTH']
3 2008 84967 ['HEALTH','LAB', 'JUST']
我想得到的是:
index year gvkey TAX ENVR HEALTH EDUC JUST LAB
0 1998 15686 1 1 1 0 0 0
1 2005 15372 1 0 1 0 1 0
2 2001 27486 1 0 1 0 1 0
3 2008 84967 0 0 1 0 1 1
在
s = pd.Series(df["code"])
l = pd.get_dummies(s.apply(pd.Series).stack()).sum(level=0)
我得到了数据的第二部分(变量 TAX、ENVR、HEALTH、EDUC、JUST 和 LAB),但丢失了第一部分(年份和 gvkey)。
如何保留年份和 gvkey 变量?
我认为更好的解决方案是使用 DataFrame.pop
with Series.str.join
and Series.str.get_dummies
:
df = df.join(df.pop('code').str.join('|').str.get_dummies())
print (df)
year gvkey EDUC ENVR HEALTH JUST LAB TAX
index
0 1998 15686 0 1 1 0 0 1
1 2005 15372 1 0 1 1 0 1
2 2001 27486 0 0 1 0 1 1
3 2008 84967 0 0 1 1 1 0
如果性能很重要,请使用 MultiLabelBinarizer
:
from sklearn.preprocessing import MultiLabelBinarizer
mlb = MultiLabelBinarizer()
df1 = pd.DataFrame(mlb.fit_transform(df.pop('code')),columns=mlb.classes_)
df = df.join(df1)
print (df)
year gvkey EDUC ENVR HEALTH JUST LAB TAX
index
0 1998 15686 0 1 1 0 0 1
1 2005 15372 1 0 1 1 0 1
2 2001 27486 0 0 1 0 1 1
3 2008 84967 0 0 1 1 1 0
您的解决方案是可行的,sum
仅适用于唯一值,对于一般解决方案需要 max
:
df = df.join(pd.get_dummies(df.pop('code').apply(pd.Series).stack()).max(level=0))
print (df)
year gvkey EDUC ENVR HEALTH JUST LAB TAX
index
0 1998 15686 0 1 1 0 0 1
1 2005 15372 1 0 1 1 0 1
2 2001 27486 0 0 1 0 1 1
3 2008 84967 0 0 1 1 1 0
您可以通过以下方法完成此操作:
方法 1:将列转换为数据框并获取 dummies ,然后 groupby
on axis=1
并获取 max:
m = pd.get_dummies(pd.DataFrame(df['code'].tolist())).groupby(lambda x:
x.split('_')[1],axis=1).max()
final1 = df.drop('code',1).assign(**m)
方法 2:使用 |
加入列列表并使用 series.str.get_dummies
final2 = df.drop('code',1).assign(**df['code'].str.join('|').str.get_dummies())
方法 3:您的方法与 concat
s = pd.Series(df["code"])
l = pd.get_dummies(s.apply(pd.Series).stack()).max(level=0)
final3 = pd.concat((df.drop('code',1),l),axis=1)
#or final = df.drop('code',1).assign(**l)