我有一个数据框' df'像这样 -
Id v1 v2
0 A 0.23
1 B 0.65
2 NaN 0.87
如果我使用
df1 = get_dummies(df)
df1
我得到了
Id v1_A v1_B v2
0 1 0 0.23
1 0 1 0.65
2 0 0 0.87 .
如何有效地获得以下内容?
Id v1_A v1_B v2
0 1 0 0.23
1 0 1 0.65
2 NaN NaN 0.87 .
我最初使用它,但需要太长时间
import numpy as np
dfv1 = df[[v1]] #Slicing the v1 column
dfs = get_dummies(dfv1)
dfsum = dfs.apply(np.sum, axis=1) #Calculating row by row sum of dfs
for i in range(dfs.size): #Iterating over the entire dataframe
if dfsum.iloc[i]==0: #and if the sum is zero for some 'i'
dfs.iloc[i][:]==np.nan #changing corresponding row to NaN
del df['v1'] #Deleting original column
df = pandas.concat([df, dfs], axis=1) #Appending the new one
我在Jupyter上使用Python 3.5.1,在Pandas上使用0.18。感谢。
答案 0 :(得分:10)
方法#1将直接使用v1
的nans,没有循环:
>>> df1 = pd.get_dummies(df)
>>> df1.loc[df.v1.isnull(), df1.columns.str.startswith("v1_")] = np.nan
>>> df1
Id v2 v1_A v1_B
0 0 0.23 1.0 0.0
1 1 0.65 0.0 1.0
2 2 0.87 NaN NaN
方法#2将使用dummy_na
参数为我们提供一个我们可以使用的列:
>>> df1 = pd.get_dummies(df, dummy_na=True)
>>> df1
Id v2 v1_A v1_B v1_nan
0 0 0.23 1.0 0.0 0.0
1 1 0.65 0.0 1.0 0.0
2 2 0.87 0.0 0.0 1.0
>>> df1.loc[df1.v1_nan == 1, ["v1_A", "v1_B"]] = np.nan
>>> del df1["v1_nan"]
>>> df1
Id v2 v1_A v1_B
0 0 0.23 1.0 0.0
1 1 0.65 0.0 1.0
2 2 0.87 NaN NaN
答案 1 :(得分:0)
我将使用一个简单的数据框作为示例:
df1 = pd.DataFrame([['A', 'A'],[np.nan, 'B'], ['C', np.nan]])
>>> df1
0 1
0 A A
1 NaN B
2 C NaN
然后对其进行单热编码:
df1_ohe = pd.get_dummies(df1, dummy_na=True)
>>> df1_ohe
0_A 0_C 0_nan 1_A 1_B 1_nan
0 1 0 0 1 0 0
1 0 0 1 0 1 0
2 0 1 0 0 0 1
现在获取这个数据框的一个子集,只包含 NaN 列:
nan_df = df1_ohe.loc[:, df1_ohe.columns.str.endswith("_nan")]
>>> nan_df
0_nan 1_nan
0 0 0
1 1 0
2 0 1
最后,使用一些正则表达式并遍历数据框中的每一行和每个 NaN 列。
如果这个位置 [row, NaN column] 包含 1,那么原始数据框上的那个位置(在 OHE 之前)是一个 NaN。
因此,我使用正则表达式来识别原始列“col_id”(即,1_nan 给我 1,这是非 OHE 数据框中包含 NaN 的列)。
所以我定位包含该位置的所有列(即 1_A、1_B 和 1_nan)并用 NaN 替换它们的值。
pattern = "^([^_]*)_"
regex = re.compile(pattern)
for index in df1_ohe.index:
for col_nan in nan_df.columns:
if df1_ohe.loc[index,col_nan] == 1:
col_id = regex.search(col_nan).group(1)
targets = df1_ohe.columns[df1_ohe.columns.str.startswith(col_id+'_')]
df1_ohe.loc[index, targets] = np.nan
给我:
>>> df1_ohe
0_A 0_C 0_nan 1_A 1_B 1_nan
0 1.0 0.0 0.0 1.0 0.0 0.0
1 NaN NaN NaN 0.0 1.0 0.0
2 0.0 1.0 0.0 NaN NaN NaN
最后,我从 OHE 数据框中删除了 NaN 列
df1_ohe.drop(df1_ohe.columns[df1_ohe.columns.str.endswith('_nan')], axis=1, inplace=True)
>>> df1_ohe
0_A 0_C 1_A 1_B
0 1.0 0.0 1.0 0.0
1 NaN NaN 0.0 1.0
2 0.0 1.0 NaN NaN