[英]How do I get started with turning columns into rows in Python Pandas?
我目前在 CSV 中有这个表。 MOL 代表男性,FOL 代表女性。 第二部分 SAL_Tagalog 是语言,SOLSE_NotWell 表示他们的语言不太好,而 SOLSE_Well 表示他们说得很好。
MOL_SAL_English_SOLSE_NotWell FOL_SAL_English_SOLSE_Well Postcode State Year
0 8 2600 ACT 2016
0 9 2601 ACT 2016
0 16 2602 ACT 2016
0 7 2603 ACT 2016
3 6 2604 ACT 2016
0 20 2605 ACT 2016
我需要将每个单元格变成自己的行,如下所示:
Sex Language Proficiency Count Postcode State Year
Male English NotWell 0 2600 ACT 2016
Female English Well 9 2600 ACT 2016
Male English NotWell 0 2601 ACT 2016
Female English Well 9 2601 ACT 2016
任何人都可以帮助我解决这个问题吗?
到目前为止,我有一个用“_”分割列名的函数,所以我最终得到 [MOL, SAL_English, SOLSE_NotWell]。 这些是进入我的新 CSV 的单元格的意思。
我目前正在尝试将其逐行写入一个新的 CSV 文件,其中包含性别、语言、熟练程度、计数、邮政编码、州和年份列。 如下所示,但我不确定如何从同一行获取相关的邮政编码和州等。
for column_name, count in df.iteritems():
new_df.Language = column_name
new_df.Count = count
这是常见的不幸场景的一个示例,其中下划线_
被用作分隔属性和空格字符的分隔符。
使用您的辅助函数将列解析为元组(Sex, Language, Proficiency)
。 我还在这里添加了第四个元素来指示它是什么类型的数据 - 这最终成为最终数据中的“计数”。 您必须编写的辅助函数通常既复杂又具有挑战性。
# Helper function
def helper_function(name):
#Use the first character to get the gender
if name[0] == 'F':
sex = 'Female'
elif name[0] == 'M':
sex = 'Male'
else:
sex = 'Other'
# The third word is the language
lang = name.split('_')[2]
# The last word is the proficiency
prof = name.split('_')[-1]
return (sex, lang, prof,'Count')
将其应用于列名将允许我们拆分重要的细节。
# Step 1
new_df = df.set_index(['Postcode', 'State', 'Year'])
# Step 2
column_tuples = [helper_function(name) for name in new_df.columns]
# Step 3
new_df.columns = pd.MultiIndex.from_tuples(column_tuples, names=['Sex','Language', 'Proficiency', 'Measure'])
# Step 4
new_df = new_df.stack(['Sex','Language', 'Proficiency']).reset_index()
多索引值得学习!
https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.MultiIndex.html
您可以使用 Pandas 的内置工具运行它:
使用pandas的melt方法将列从宽翻转为长,这样可以更容易地提取细节其余的是pandas 字符串方法、 regex和map的组合
#mapping for sex column which we'll create
sex_map = {'MOL':'Male', 'FOL':'Female'}
(df
#flip the columns from wide to long
.melt(id_vars=['Postcode','State','Year'],value_name='count')
#extract the required columns
#sex is either MOL or FOL, which is the first characters before _
.assign(Sex=lambda x:x.variable.str.split('_').str[0],
#proficiency is the grp of characters after the last _
Proficiency = lambda x: x.variable.str.split('_').str[-1],
# a bit of regex here,
#basically get the word between SAL_ and _SOL
Language = lambda x: x.variable.str.extract(r'((?<=SAL_).*(?=_SOL))')
)
#use the sex_map dictionary to get the right entries(male|female)
.assign(Sex = lambda x: x.Sex.map(sex_map))
#remove the unwanted column
.drop('variable',axis=1)
)
这是另一种选择,但可能更长:它是宽到长、 堆栈和字符串方法的组合。
sex_mapping = {'MOL_SAL':'Male', 'FOL_SAL':'Female'}
(pd.wide_to_long(df,
stubnames=['MOL_SAL','FOL_SAL'],
i=['Postcode','State', 'Year'],
j='proficiency',
sep='_',
suffix='[\w_]+'
)
.stack()
.reset_index()
.rename(columns={'level_4':'Sex',0:'count'})
.assign(language = lambda x: x.proficiency.str.extract(r'(.*?(?=_))'),
proficiency = lambda x: x.proficiency.str.rsplit('_').str[-1],
Sex = lambda x: x.Sex.map(sex_mapping)
)
)
#first couple of rows
Postcode State Year proficiency Sex count language
0 2600 ACT 2016 NotWell Male 0.0 English
1 2600 ACT 2016 Well Female 8.0 English
2 2601 ACT 2016 NotWell Male 0.0 English
3 2601 ACT 2016 Well Female 9.0 English
4 2602 ACT 2016 NotWell Male 0.0 English
5 2602 ACT 2016 Well Female 16.0 English
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.