转置数据帧,但仅保留非零值

2024-10-05 10:21:19 发布

您现在位置:Python中文网/ 问答频道 /正文

数据帧:

让我澄清我的问题。我的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']

然后,我根据“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. 我的数据框很大。它包含近百万行,超过15Word*类型的列和超过115C*类型的列(word*C*是我在示例中使用的列名)
  2. 我将Python 2.7Pandas 0.17一起使用

Tags: columns数据dfvaluec2c1word1word2
2条回答

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

实际上,您的任务不是换位,而是类似于堆栈, 限制为非零值,并添加一些内容,即行 包含您希望输出包含的所有零(从C1C4word1word3的值,以及:

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

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

  1. 包含C1C4列堆栈的系列,带有 word1word3移动到索引和索引的最后一级 重命名为变量

    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. 包含所有零的行的输出结果(从C1C4):

    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“重新生成”结果中的索引

要跟踪此解决方案的工作方式,请同时打印s[s > 0].reset_index() 一切都应该清楚

相关问题 更多 >

    热门问题