【问题标题】:python pandas pivot: How to do a proper tidyr-like spread?python pandas pivot:如何进行适当的类似tidyr的传播?
【发布时间】:2023-06-20 13:47:01
【问题描述】:

我缺少在 Python 中从长到宽的自发且轻松的转换,反之亦然。 想象一下,我有一个大而整洁的数据框,其中包含许多属性列和一个包含所有实际值的列,例如

PropA ... PropZ    Value
green     Saturn   400
green     Venus    3
red       Venus    2
.
.

通过保持整洁,数据本身得到了很好的处理。但有时我必须对某些属性执行一些操作(例如,比较蜜蜂红和蜜蜂绿色可能会很有趣(对于与其他属性相似的所有项目))。 所以直截了当的方法是尽可能保持整洁,并且只打乱我感兴趣的某些属性(PropA)。随后,我可以使用我想要的任何函数执行逐行映射,并且可以创建一个包含函数输出的附加 PropA-Entry。

但是,在 Python 中保持所有其他属性整洁并不像我以前使用 R 那样容易。原因是,所有非关键属性都通过我找到的所有 pd 方法提交给索引。如果我还想保留更多的专栏,那真是一团糟。

那么你是如何解决这个问题的。有没有其他巧妙的方法来处理这些类型的问题?


我自己编写了一个传播方法,但是速度非常慢。也许,您对我可以如何改进有一些想法。

#the idea is to group by the remaining properties, which should be left in the long format.
#then i spread the small tidy data table for any group
    @staticmethod
    def spread(df, propcol, valcol):
        def flip(data,pc,vc):
            data = data.reset_index(drop=True)
            return {data[pc][i]:[data[vc][i]] for i in range(0,len(data))}

        #index columns are all which are not affected
        indcols = list(df.columns)
        indcols.remove(propcol)
        indcols.remove(valcol)

        tmpdf=pd.DataFrame()
        for key, group in df.groupby(indcols):
            dc1 = {a:[b] for (a,b) in zip(indcols,key)}
            dc2 = flip(group,propcol,valcol)
            tmpdf = pd.concat([tmpdf,pd.concat([pd.DataFrame(dc1),pd.DataFrame(dc2)],axis=1)])

        return tmpdf.reset_index(drop = True)

【问题讨论】:

  • 多索引不够吗?有一个合理的解释here
  • 感谢链接。那么这是否意味着:通过分层索引来组织整齐的数据会更好?因此,我应该通过将所有属性传递给索引并只保留 value 列来整理我的所有数据。但这似乎有点不方便,因为大部分信息都包含在索引中。此外,我的属性是可以互换的,并不是真正的层次结构。

标签: python pandas pivot spread


【解决方案1】:

在提示的帮助下,我创建了一个更简单的版本。 我仍然对索引机制有些困惑,但时间会帮助我更好地理解。

def spread(df, propcol, valcol):
    indcol = list(df.columns.drop(valcol))
    df = df.set_index(indcol).unstack(propcol).reset_index()
    df.columns = [i[1] if i[0] == valcol else i[0] for i in df.columns]
    return df

【讨论】:

    最近更新 更多