<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          一道基礎(chǔ)題,多種解題思路,引出Pandas多個(gè)知識(shí)點(diǎn)

          共 4292字,需瀏覽 9分鐘

           ·

          2021-12-02 11:39

          小小明:「凹凸數(shù)據(jù)」專欄作者,Pandas數(shù)據(jù)處理高手,致力于幫助無(wú)數(shù)數(shù)據(jù)從業(yè)者解決數(shù)據(jù)處理難題。

          源于林胖發(fā)出的一道基礎(chǔ)題:

          基礎(chǔ)解法explode函數(shù)

          這道題最簡(jiǎn)單的解法,相信大部分用過(guò)pandas的朋友都會(huì),林胖也馬上發(fā)出了自己的答案:

          import?pandas?as?pd

          mydict?=?{'A':?[1],?'B':?[2,?3],?'C':?[4,?5,?6]}
          pd.DataFrame(mydict.items()).explode(1)

          結(jié)果:

          詳解

          mydict.items()是python基礎(chǔ)字典的內(nèi)容,它返回了這個(gè)字典鍵值對(duì)組成的元組列表:

          mydict.items()

          返回:

          dict_items([('A',?[1]),?('B',?[2,?3]),?('C',?[4,?5,?6])])

          將這個(gè)內(nèi)部是元組的可迭代對(duì)象傳入DataFrame的構(gòu)造函數(shù)中:

          pd.DataFrame(mydict.items())

          返回結(jié)果:

          這是pandas最基礎(chǔ)的開(kāi)篇知識(shí)點(diǎn)使用可迭代對(duì)象構(gòu)造DataFrame,列表的每個(gè)元素都是整個(gè)DataFrame對(duì)應(yīng)的一行,而這個(gè)元素內(nèi)部迭代出來(lái)的每個(gè)元素將構(gòu)成DataFrame的某一列。

          然后再看看這個(gè)explode函數(shù),它是pandas 0.25版本才出現(xiàn)的函數(shù),只有一個(gè)參數(shù)可以傳入列名,然后該函數(shù)就可以把該列的列表每個(gè)元素?cái)U(kuò)展到多行上。

          效果與hive使用lateral view+explode實(shí)現(xiàn)的效果幾乎一致,類似于:

          select?a,b_i?from?df?lateral?view?explode(b)?tmp?as?b_i;

          可以參考很早之前的一篇文章:https://blog.csdn.net/as604049322/article/details/105985770

          沒(méi)有exlode函數(shù)如何解決這個(gè)問(wèn)題

          但是,黃佬說(shuō)版本太低沒(méi)有這個(gè)函數(shù),于是我給群友們出了一道題:

          在黃佬的邀請(qǐng)下,一位經(jīng)過(guò)我多次輔導(dǎo)的群友率先使用了循環(huán)法解題:

          我覺(jué)得非常棒,但我也希望看到有人再用變形法實(shí)現(xiàn)一次。林胖和一位群友再次給出了簡(jiǎn)化版本的循環(huán)解法:

          經(jīng)過(guò)一番提示后,小五哥和林胖終于給出了變形法的解法:

          非常不錯(cuò),群友們終于獨(dú)立的多思路解決了這個(gè)問(wèn)題,真的要撒花呀!?。?/p>

          下面我們?cè)敿?xì)分析一下,循環(huán)法和變形法的解法吧:

          循環(huán)法解題

          基本寫(xiě)法:

          result?=?[]
          for?k,?vs?in?mydict.items():
          ????for?v?in?vs:
          ????????result.append((k,?v))
          pd.DataFrame(result)

          本質(zhì)上就是實(shí)現(xiàn)了一個(gè)笛卡爾積的拉平操作,將mydict.items這個(gè)可迭代對(duì)象的元組構(gòu)造笛卡爾積并按照整體拉平。

          上面的基本寫(xiě)法,應(yīng)該99%以上的朋友都能看懂,但 林胖 的循環(huán)簡(jiǎn)化解法:

          import?itertools
          result?=?[]
          for?k,?v?in?mydict.items():
          ????result.extend(itertools.product(k,?v))
          pd.DataFrame(result)

          部分朋友可能沒(méi)有看明白,這個(gè)就需要查詢一下product方法的官方文檔(https://docs.python.org/zh-cn/3.7/library/itertools.html?highlight=product#itertools.product):

          product(*iterables,?repeat=1)?-->?product?object

          參數(shù):

          • iterables 為可迭代對(duì)象
          • 可選參數(shù)repeat 表示重復(fù)次數(shù)

          用于生成可迭代對(duì)象輸入的笛卡兒積,相當(dāng)于生成器表達(dá)式中的嵌套循環(huán)。

          例如:product(A, B) 中的元素A和B將共同構(gòu)成可迭代元素[A, B]作為iterables傳入和 ((x,y) for x in A for y in B) 返回結(jié)果一樣。

          返回示例:

          • product(‘a(chǎn)b’, range(3)) --> (‘a(chǎn)’,0) (‘a(chǎn)’,1) (‘a(chǎn)’,2) (‘b’,0) (‘b’,1) (‘b’,2)
          • product((0,1), (0,1), (0,1)) --> (0,0,0) (0,0,1) (0,1,0) (0,1,1) (1,0,0) …

          也可以傳入可選參數(shù) repeat 表示重復(fù)的次數(shù):例如,product(A, repeat=4)product(A, A, A, A) 的返回結(jié)果是一樣的。


          列表的extend方法是將可迭代對(duì)象的每個(gè)元素都添加到列表中,而append方法只能添加單個(gè)元素。

          當(dāng)然,我們還可以將整個(gè)for循環(huán)改寫(xiě)成列表生成式:

          result?=?[(k,?v)?for?k,?vs?in?mydict.items()?for?v?in?vs]
          pd.DataFrame(result)

          也可以簡(jiǎn)化代碼量。

          變形法解題

          df?=?pd.DataFrame(mydict.items(),?columns=["a",?"b"])
          df

          實(shí)現(xiàn)思路,上面的界面是下面最左邊:

          列表分列的2種方法

          列表分列的思路:Pandas的Series對(duì)象調(diào)用apply方法單個(gè)元素返回的結(jié)果是Series時(shí),這個(gè)Series的每個(gè)數(shù)據(jù)會(huì)作為Datafrem的每一列,索引會(huì)作為列名。

          對(duì)Series進(jìn)行列表分列

          例如:

          df["b"].apply(pd.Series)

          結(jié)果:

          不過(guò)這樣會(huì)丟失原本的"a"列,我們可以先將"a"列設(shè)置為索引,再進(jìn)行Series分列操作:

          df.set_index("a")["b"].apply(pd.Series)

          或者把結(jié)果設(shè)置成原本的"a"列為索引:

          df["b"].apply(pd.Series).set_index(df["a"])

          結(jié)果均為上述實(shí)現(xiàn)思路的第二步。

          直接對(duì)Datafream進(jìn)行列表分列

          如果我們希望直接使用Datafream實(shí)現(xiàn)分列可以借助agg方法,因?yàn)閍gg方法是對(duì)每一列的Series對(duì)象操作:

          df.agg({"a":?lambda?x:?x,?"b":?pd.Series})

          結(jié)果:

          但這操作導(dǎo)致列多了一個(gè)級(jí)別,需要?jiǎng)h除:

          df.agg({"a":?lambda?x:?x,?"b":?pd.Series}).droplevel(0,?axis=1)

          結(jié)果:

          只要再執(zhí)行set_index("a")

          df.agg({"a":?lambda?x:?x,?"b":?pd.Series}).droplevel(0,?axis=1).set_index("a")

          結(jié)果就會(huì)與實(shí)現(xiàn)思路的第二步結(jié)果一致。

          將字典的鍵作為索引的2種讀取方法

          當(dāng)然上面我只是為了給大家講述分列的一些方法。對(duì)于這個(gè)例子,其實(shí)我們可以直接通過(guò)pd.DataFrame.from_dict方法orient參數(shù)傳入’index’,直接獲得第二步的結(jié)果(只是索引沒(méi)有名稱):

          df?=?pd.DataFrame.from_dict(mydict,?'index')

          或者分別傳入data和索引index:

          df?=?pd.DataFrame(data=mydict.values(),?index=mydict.keys())

          都能得到以下結(jié)果:

          melt實(shí)現(xiàn)逆透視

          說(shuō)起逆透視我個(gè)人首先想到了melt方法,然后才想到melt方法實(shí)現(xiàn)的本質(zhì)用到了stack方法。

          為了避免索引丟失,我們首先還原索引為普通的列:

          df?=?df.rename_axis(index="a").reset_index()
          df

          結(jié)果:

          然后使用melt方法進(jìn)行逆透視:

          df.melt(id_vars='a',?value_name='b')

          結(jié)果:

          然后刪除第二列,再刪除空值行,再將數(shù)值列轉(zhuǎn)換為整數(shù)類型就搞定。

          最終代碼:

          df?=?pd.DataFrame.from_dict(mydict,?'index')
          df?=?df.melt(id_vars='a',?value_name='b').drop(columns="variable").dropna()
          df.b?=?df.b.astype("int")
          df

          成功得到結(jié)果:

          stack實(shí)現(xiàn)逆透視

          df?=?pd.DataFrame.from_dict(mydict,?'index')
          df.stack()

          結(jié)果:

          A??0????1.0
          B??0????2.0
          ???1????3.0
          C??0????4.0
          ???1????5.0
          ???2????6.0
          dtype:?float64

          結(jié)果返回了一個(gè)多級(jí)索引的Series,我們首先需要?jiǎng)h除索引中多余的部分:

          df.stack().droplevel(1)

          結(jié)果:

          A????1.0
          B????2.0
          B????3.0
          C????4.0
          C????5.0
          C????6.0
          dtype:?float64

          此時(shí)我們?cè)龠€原索引到普通列:

          df.stack().droplevel(1).reset_index()

          再重新設(shè)置一下列名:

          df.stack().droplevel(1).reset_index().set_axis(["a",?"b"],?axis=1)

          最后重設(shè)一下B列的類型:

          df.b?=?df.b.astype("int")

          最終代碼:

          df?=?pd.DataFrame.from_dict(mydict,?'index')
          df?=?df.stack().droplevel(1).reset_index().set_axis(["a",?"b"],?axis=1)
          df.b?=?df.b.astype("int")
          df

          結(jié)果:

          歡迎你在下方評(píng)論區(qū)留言,發(fā)表你的看法,給大家分享和互動(dòng)!

          如果大家喜歡我的文章,請(qǐng)動(dòng)動(dòng)你的小手,點(diǎn)個(gè)贊吧~

          我們的文章到此就結(jié)束啦,如果你喜歡今天的Python 實(shí)戰(zhàn)教程,請(qǐng)持續(xù)關(guān)注Python實(shí)用寶典。

          有任何問(wèn)題,可以在公眾號(hào)后臺(tái)回復(fù):加群,回答相應(yīng)紅字驗(yàn)證信息,進(jìn)入互助群詢問(wèn)。

          原創(chuàng)不易,希望你能在下面點(diǎn)個(gè)贊和在看支持我繼續(xù)創(chuàng)作,謝謝!

          點(diǎn)擊下方閱讀原文可獲得更好的閱讀體驗(yàn)

          Python實(shí)用寶典?(pythondict.com)
          不只是一個(gè)寶典
          歡迎關(guān)注公眾號(hào):Python實(shí)用寶典

          瀏覽 55
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲无码视频网站 | 国产午夜视频在线观看 | 人人艹人人干 | 男人天堂2014 | 在线观看亚洲免费 |