DataFrame:
让我澄清我的问题。我的pandas.DataFrame
看起来像这样
data = [
['word11', 'word12', 'word13', 'word14', 0, 0, 0, 0, 0],
['word21', 'word22', 'word23', 'word24', 0, -3, 34, 0, 0],
['word31', 'word32', 'word33', 'word34', 0, 1.6, 0, 0, 0],
['word41', 'word42', 'word43', 'word44', 0, 0, 0, 0, 0]
]
df = pd.DataFrame(data, columns=['word1', 'word2', 'word3', 'word4', 'C1', 'C2', 'C3', 'C4', 'C5'])
要生成的输出:
由此,我想获得一个看起来像
的数据框 word1 word2 word3 word4 C1 C2 C3 C4 C5
0 word11 word12 word13 word14 0 0.0 0 0 0
1 word21 word22 word23 word24 0 -3.0 34 0 0
2 word31 word32 word33 word34 0 1.6 0 0 0
3 word41 word42 word43 word44 0 0.0 0 0 0
我的程序:
这是我获取上述数据框的步骤
primary_columns = ['word1', 'word2', 'word3', 'word4']
transposing_columns = ['C1', 'C2', 'C3', 'C4', 'C5']
transposed_df = df.melt(id_vars=primary_columns, value_vars=transposing_columns)
compare_columns = primary_columns + ['value']
然后,我根据“值”列的值将数据框分为两部分,并删除重复项。
nonzero_df = transposed_df[transposed_df['value'] != 0]
zero_df = transposed_df[transposed_df['value'] == 0]
zero_df = zero_df.drop_duplicates(subset=compare_columns, keep='first')
df = nonzero_df.append(zero_df)
哪个给了我以下输出
df = df.reset_index(drop=True)
df
word1 word2 word3 word4 variable value
0 word21 word22 word23 word24 C2 -3.0
1 word31 word32 word33 word34 C2 1.6
2 word21 word22 word23 word24 C3 34.0
3 word11 word12 word13 word14 C1 0.0
4 word21 word22 word23 word24 C1 0.0
5 word31 word32 word33 word34 C1 0.0
6 word41 word42 word43 word44 C1 0.0
问题:
我不想看到df.iloc[4]
和df.iloc[5]
。
如果word1
,word2
,word3
和word4
的值相同,但仅在value
列中有所不同,请保留该行非零值并删除具有0值的行。我不在乎列variable
的值。
我该如何实现?
注意:
Word*
类型的列和超过115 C*
类型的列(word*
和C*
是我在示例中使用的列名)。 Python 2.7
与Pandas 0.17
一起使用。答案 0 :(得分:1)
实际上,您的任务不是换位,而是 stack 之类的东西, 限制为非零值,并为行添加一些附加值 包含要输出包含的所有零(在 C1 至 C4 中) word1 到 word3 和:
为此,请计算2个中间变量:
一个系列,其中包含 C1 至 C4 列的堆栈, word1 至 word3 移至索引和索引的最后一级 重命名为变量:
s = df.set_index(['word1', 'word2', 'word3']).stack().rename('value')
s.index.rename('variable', level=3, inplace=True)
对于您的输入数据,结果为:
word1 word2 word3 variable
word11 word12 word13 C1 0
C2 0
C3 0
C4 0
word21 word22 word23 C1 0
C2 1
C3 1
C4 0
word31 word32 word33 C1 1
C2 0
C3 0
C4 1
Name: value, dtype: int64
包含全零的行(在 C1 至 C4 中)的输出结果:
dfZer = df[df.loc[:, 'C1':'C4'].sum(axis=1) == 0].loc[:, 'word1':'word3']\
.assign(variable='C1', value=0)
对于您的数据,结果为:
word1 word2 word3 variable value
0 word11 word12 word13 C1 0
然后生成最终结果为:
pd.concat([s[s > 0].reset_index(), dfZer], sort=False, ignore_index=True)
请注意:
s[s > 0]
删除值为 0 ,reset_index()
提供“全零”输入行的结果,dfZer
“重新生成”结果中的索引。要跟踪此解决方案的工作方式,请同时打印ignore_index=True
一切都应该清楚。
答案 1 :(得分:1)
IIUC,您想在每一行中保留所有1
。并且如果该行上所有0
,请保留任何值:
d = (df.melt(['word1','word2','word3'])
.sort_values('value', ascending=False)
)
d[~d.duplicated(['word1','word2','word3']) | d['value']]
输出:
word1 word2 word3 variable value
2 word31 word32 word33 C1 1
4 word21 word22 word23 C2 1
7 word21 word22 word23 C3 1
11 word31 word32 word33 C4 1
0 word11 word12 word13 C1 0