在pivot_longer中使用regex来取消具有公共分组变量的多列集



接着我上一个问题:Pyjanitor pivot_longer多列集,具有公共分组变量和id列

在我的最后一个问题中,我给出的数据集对于我所遇到的问题来说过于简化了。我已经改变了列名来代表我的数据集中的列名,因为我不知道如何在pivot_longer中使用regex来修复它们。在我给出的模型数据集中,列是用以下模式编写的:number_word,但在我的数据集中,列是任意顺序的,从不用下划线分隔(例如,wordnumber)。

注意,每个列集的编号需要是相同的分组变量。因此,每个数字都应该有一个评级、估计和类型。

数据集

df = pd.DataFrame({
'id': [1, 1, 1],
'ratingfirst': [1, 2, 3],
'ratingsecond': [2.8, 2.9, 2.2],
'ratingthird': [3.4, 3.8, 2.9],
'firstestimate': [1.2, 2.4, 2.8],
'secondestimate': [2.4, 3, 2.4],
'thirdestimate':[3.4, 3.8, 2.9],
'firsttype': ['red', 'green', 'blue'],
'secondtype': ['red', 'green', 'yellow'],
'thirdtype': ['red', 'red', 'blue'],
})

期望输出值

我想要的输出的标题如下:

<表类>id类别评级估计类型tbody><<tr>1第一个1.01.2"红色">

我认为最简单的方法是将您的列与上一个问题中使用的列对齐,例如:

def fix_col_header(s, d):
for word, word_replace in d.items():
s = s.replace(word, word_replace)
if s.startswith("_"):
s = s[len(word_replace):] + s[:len(word_replace)]
return s
d = {"first":"_first", "second":"_second", "third": "_third"}
df.columns = [fix_col_header(col, d) for col in df.columns]

这将给列:

id, rating_first, rating_second, rating_third, estimate_first, estimate_second, estimate_third, type_first, type_second, type_third

现在您可以应用上一个问题的解决方案(注意,类别和值是互换的)。为了完整起见,我在这里添加了它:

import janitor
(df
.pivot_longer(
column_names="*_*", 
names_to = (".value", "category"), 
names_sep="_")
)

pivot_longer支持多个.value-您可以利用这一点来重塑您的数据框,使用names_sep参数:

# pip install pyjanitor
import pandas as pd
import janitor
(df
.pivot_longer(
index='id',
names_to = (".value", "category", ".value"),
names_sep = "(first|second|third)")
)
id category  rating  estimate    type
0   1    first     1.0       1.2     red
1   1    first     2.0       2.4   green
2   1    first     3.0       2.8    blue
3   1   second     2.8       2.4     red
4   1   second     2.9       3.0   green
5   1   second     2.2       2.4  yellow
6   1    third     3.4       3.4     red
7   1    third     3.8       3.8     red
8   1    third     2.9       2.9    blue

如果你看一下分解,你可以看到这里发生了什么:

df.columns[1:].str.split("(first|second|third)")
Index([   ['rating', 'first', ''],   ['rating', 'second', ''],
['rating', 'third', ''],  ['', 'first', 'estimate'],
['', 'second', 'estimate'],  ['', 'third', 'estimate'],
['', 'first', 'type'],     ['', 'second', 'type'],
['', 'third', 'type']],
dtype='object')

注意我们有三个条目,其中一个是空字符串。这与我们的names_to参数匹配->(".value", "category", ".value");一旦pivot_longer匹配,它就会在最终输出中将.value合并为一个,因此对于['rating', 'first', ''],它将取出('rating', ''),并最终将它们合并为一个->rating,并以此类推。

另一个选项是pd.stack:
temp = df.set_index('id')
temp.columns = temp.columns.str.split("(first|second|third)", expand = True)
temp.columns.names = [None, 'category', None]
temp = temp.stack('category')
temp.columns = temp.columns.map("".join)
temp.reset_index()
id category  estimate    type  rating
0   1    first       1.2     red     1.0
1   1   second       2.4     red     2.8
2   1    third       3.4     red     3.4
3   1    first       2.4   green     2.0
4   1   second       3.0   green     2.9
5   1    third       3.8     red     3.8
6   1    first       2.8    blue     3.0
7   1   second       2.4  yellow     2.2
8   1    third       2.9    blue     2.9

最新更新