繁体   English   中英

如何开始在 Python Pandas 中将列转换为行?

[英]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

这是常见的不幸场景的一个示例,其中下划线_被用作分隔属性和空格字符的分隔符。

  1. 首先,将邮政编码、州和年份拉到索引中,只是为了让它们不碍事。
  2. 然后,使用辅助函数将剩余的列拆分为有意义的元组
  3. 然后将这些元组升级为多索引。 在那时候,
  4. 我们完成了 - 但我们只需要重塑数据。

使用您的辅助函数将列解析为元组(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 字符串方法regexmap的组合

 #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.

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