转置熊猫数据框,但仅保留非零值

时间:2020-03-14 19:01:47

标签: python pandas dataframe

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]

如果word1word2word3word4的值相同,但仅在value列中有所不同,请保留该行非零值并删除具有0值的行。我不在乎列variable的值。

我该如何实现?

注意:

  1. 我的数据框很大。它包含近百万行,超过15个Word*类型的列和超过115 C*类型的列(word*C*是我在示例中使用的列名)。
  2. 我将Python 2.7Pandas 0.17一起使用。

2 个答案:

答案 0 :(得分:1)

实际上,您的任务不是换位,而是 stack 之类的东西, 限制为非零值,并为行添加一些附加值 包含要输出包含的所有零(在 C1 C4 中) word1 word3 和:

  • 变量=='C1'
  • 值== 0

为此,请计算2个中间变量:

  1. 一个系列,其中包含 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
    
  2. 包含全零的行(在 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
相关问题