将 n 列转换为行

3
我正在寻找一种从pandas df中单行解构数据的方法。
我的数据看起来像这样。
编辑:n代表未指定的数字,例如在我的工作数据集中,我有8个图形,给我8 x 2 = 16列我想要转换。
data = {
        'key':['k1', 'k2'],
        'plot_name_1':['name', 'name'],
        'plot_area_1':[1,2],
        'plot_name_2':['name', 'name'],
        'plot_area_2':[1,2],
        'plot_name_n':['name', 'name'],
        'plot_area_n':[1,2]
       }

df = pd.DataFrame(data)

enter image description here

我想在这里结束,添加一个额外的列来标识情节编号:

data = {
        'key':['k1','k1','k1', 'k2', 'k2', 'k2'],
        'plot_number':['1', '2', 'n','1', '2', 'n'],
        'plot_name':['name', 'name','name', 'name','name', 'name'],
        'plot_area':[1,2,1,2,1,2],
       }

df = pd.DataFrame(data)

enter image description here


pd.wide_to_long(df, stubnames=['plot_name', 'plot_area'], i='key', j='plot_number', sep='_') - mozway
@mozway - 没有按照预期考虑 plot_name_nplot_area_n - ScottC
2
@ScottC 我认为 n 是一个通用术语,用于表示任何数字,但很容易处理(我看到 @Mustafa 已经做到了)。 - mozway
2个回答

5

pd.wide_to_long 可以实现这个功能:

In [160]: pd.wide_to_long(df, stubnames=["plot_name", "plot_area"],
                          i="key", j="plot_number",
                          sep="_", suffix=r"(?:\d+|n)").reset_index()
Out[160]:
  key plot_number plot_name  plot_area
0  k1           1      name          1
1  k2           1      name          2
2  k1           2      name          1
3  k2           2      name          2
4  k1           n      name          1
5  k2           n      name          2

在哪里

  • "stubnames" 是要捕获的公共列前缀名称
  • "sep" 是这些前缀后面的分隔符
    • 在您的情况下为“_”
  • "suffix" 是分隔符后预期的内容
    • 一个或多个数字,或者在您的情况下是字面上的“n”; 如果“n”是象征性的,则可以在那里使用suffix=r"\d+"
  • "i" 参数是“索引”(即标识符变量)
  • "j" 表示收集后缀的名称。

顺带一提,当存在多个后缀时,我们需要在正则表达式周围加括号,因为pandas在构建正则表达式时使用suffix时的内部机制如此。
regex = rf"^{re.escape(stub)}{re.escape(sep)}{suffix}$"

我们可以看到,suffix 直接被插值,而其中的交替器(即 |)会将左侧视为不仅是 \d+,还包括来自 stub 和 sep 的内容。

1
后缀可以是 . - sammywemmy
1
同意(.+ 用于泛化),但如果由于某些原因需要排除某些存根,则明确的模式可能会有所帮助。 - Mustafa Aydın

5

一种选择是使用pyjanitor中的pivot_longer进行重塑,使用正则表达式来捕获组:

# pip install pyjanitor
import pandas as pd
import janitor

(df
.pivot_longer(
    index='key', 
    names_to = ('.value', 'plot_number'), 
    names_pattern = r"(.+)_(.+)")
)
  key plot_number plot_name  plot_area
0  k1           1      name          1
1  k2           1      name          2
2  k1           2      name          1
3  k2           2      name          2
4  k1           n      name          1
5  k2           n      name          2

.value 确定哪些列的部分保留为标题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接