繁体   English   中英

重塑 Pandas DataFrame Python 3.x

[英]Reshaping pandas DataFrame Python 3.x

我有一只像这样的熊猫:

df =
cid    pid     purl    tid   turl     sid   surl
c1      p1     urlp1   t1    urlt1    s1    urls1
c1      p1     urlp1   t1    urlt1    s2    urls2
c1      p1     urlp1   t1    urlt1    s3    urls3
c2      p2     urlp2   t2    urlt2    s5    urls5
c2      p2     urlp2   t2    urlt2    s6    urls6

我想要的是这样的结果:

cid     uid      url
c1      p1      urlp1 
c1      t1      urlt1
c1      s1      urls1   
c1      s2      urls2
c1      s3      urls3
c2      p2      urlp2   
c2      t2      urlt2
c2      s5      urls5
c2      s6      urls6

我尝试使用pd.melt来实现这一点,但我只能像这样部分地做到这一点:

df2 = pd.melt(df, id_vars = 'cid', value_vars = ['pid','tid','purl'], value_name = 'userid')

如何获得更多的列? 我需要更多列value_name吗? 我怎样才能做到这一点?

一种手动解决方案是使用列表理解。 步骤是:

  1. 将索引设置为键列cid
  2. 从列数计算列表推导循环的长度。
  3. concat与数据框列表一起使用,并通过pipe重命名列[如果需要,添加其他格式]。
  4. 最后, reset_index (将索引提升为一系列)和drop_duplicates

这是一个演示:

df = df.set_index('cid')

def formatter(df):
    df.columns = ['uid', 'url']
    return df

n = int(len(df.columns) / 2)
L = [df.iloc[:, 2*i:2*(i+1)].pipe(formatter) for i in range(n)]
res = pd.concat(L, axis=0).reset_index().drop_duplicates()

print(res)

   cid uid    url
0   c1  p1  urlp1
3   c2  p2  urlp2
5   c1  t1  urlt1
8   c2  t2  urlt2
10  c1  s1  urls1
11  c1  s2  urls2
12  c1  s3  urls3
13  c2  s5  urls5
14  c2  s6  urls6

不确定这是最简单的方法,但这是我能想到的:

import pandas as pd
from io import StringIO

s = """cid    pid     purl    tid   turl     sid   surl
c1      p1     urlp1   t1    urlt1    s1    urls1
c1      p1     urlp1   t1    urlt1    s2    urls2
c1      p1     urlp1   t1    urlt1    s3    urls3
c2      p2     urlp2   t2    urlt2    s5    urls5
c2      p2     urlp2   t2    urlt2    s6    urls6"""

df = pd.read_table(StringIO(s), sep='\\s+', header=0)
df2 = df.set_index('cid')
df3 = pd.concat([df2[['pid', 'purl']].rename(columns={'pid': 'uid', 'purl': 'url'}),
                 df2[['tid', 'turl']].rename(columns={'tid': 'uid', 'turl': 'url'}),
                 df2[['sid', 'surl']].rename(columns={'sid': 'uid', 'surl': 'url'})],
                axis=0)
result = df3.drop_duplicates().sort_index().reset_index()
print(result)

输出:

  cid uid    url
0  c1  p1  urlp1
1  c1  t1  urlt1
2  c1  s1  urls1
3  c1  s2  urls2
4  c1  s3  urls3
5  c2  p2  urlp2
6  c2  t2  urlt2
7  c2  s5  urls5
8  c2  s6  urls6

这些列有一个模式 -> 有些以id结尾,有些以url结尾。

我们可以使用这种模式来重塑数据,并删除重复项。

这只是一个替代方案,并且依赖pyjanitorpivot_longer来帮助重塑过程:

# pip install pyjanitor
import pandas as pd
import janitor as jn
(df.pivot_longer(index = 'cid', 
                 names_to = ('uid', 'url'), 
                 names_pattern = (r".+id", r".+url"), 
                 sort_by_appearance = True)
   .drop_duplicates(ignore_index = True)
)
  cid uid    url
0  c1  p1  urlp1
1  c1  t1  urlt1
2  c1  s1  urls1
3  c1  s2  urls2
4  c1  s3  urls3
5  c2  p2  urlp2
6  c2  t2  urlt2
7  c2  s5  urls5
8  c2  s6  urls6

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM