iT邦幫忙

1

Python DataFrame 操作

各位好

最近在學Python,遇到了兩個問題撞牆不知道怎麼解,還請各位給些指點,謝謝。


Q1:
有個df
memberid order_date
a 2020-08-05
a 2020-08-12
a 2020-08-17
b 2020-08-16
b 2020-08-19
c 2020-05-01
c 2020-05-03
c 2020-05-04
c 2020-05-07
要怎麼樣才能找到類似group by memberid 但顯示的是倒數第二筆資料呢
(想像的樣子)
a 2020-08-12
b 2020-08-16
c 2020-05-04


Q2:因為是學SQL慢慢有興趣開始學python 轉換過來一直覺得sql的case when條件式很好用 轉換到python之後 都用apply(lambda x:...) 但最近想轉換str都一直失敗 想請問有沒有別的方法 謝謝

舉例來說
memberid campaign
a bthd
a bthd_sell
a urgent_s
b urgent_s
b urgent_s
c bthd_sell
c bthd_sell
c   christmas
c christmas
想依照條件 campaign == 'bthd_sell', campaign == 'urgent_s' 新開一欄命名為1,2
memberid campaign cam_label
a bthd
a bthd_sell 1
a urgent_s 2
b urgent_s 2
b urgent_s 2
c bthd_sell 1
c bthd_sell 1
c christmas
c christmas
*考慮過用map(dict) 但我目前處理的表該變數有太多種類 只想特定幾個處理一下 其他就null 想問有沒有更方便的解法

小弟有努力在搜索相關資源 嘗試不當伸手牌 但因為入門不久 對相關terms的概念也不深 找不太到相關回答 如果是已經存在的問題 還請鞭小力一點 謝謝各位幫忙了 祝大家周末愉快!

4
listennn08
iT邦高手 6 級 ‧ 2020-08-21 18:45:11
最佳解答

pandas 搭配 numpy
我語法也是 google 來的,給你關鍵字參考

  1. dataframe group by get second row
    pandas dataframe groupby and get nth row
  2. dataframe add column in condition
    Add a Column to a Pandas DataFrame Based on an If-Else Condition
import pandas as pd
import numpy as np

df = pd.DataFrame(
  np.array([
    ["a", "2020-08-05"], 
    ["a", "2020-08-12"],
    ["a", "2020-08-17"],
    ["b", "2020-08-16"],
    ["b", "2020-08-19"],
    ["c", "2020-05-01"],
    ["c", "2020-05-03"],
    ["c", "2020-05-04"],
    ["c", "2020-05-07"]]),
  columns=["memberid", "order_date"]
)
print(df.groupby('memberid').nth(-2).dropna())

#              order_date
#    memberid
#    a         2020-08-12
#    b         2020-08-16
#    c         2020-05-04


df1 = pd.DataFrame(
  np.array([
    ["a", "bthd"],
    ["a", "bthd_sell"],
    ["a", "urgent_s"],
    ["b", "urgent_s"],
    ["b", "urgent_s"],
    ["c", "bthd_sell"],
    ["c", "bthd_sell"],
    ["c", "christmas"],
    ["c", "christmas"]]),
  columns=["memberid","campaign"]
)


df1['cam_label'] = np.where(df1['campaign'] == 'bthd_sell', 1, np.where(df1['campaign'] == 'urgent_s', 2, ''))
print(df1)
#    memberid   campaign cam_label
#    0        a       bthd
#    1        a  bthd_sell         1
#    2        a   urgent_s         2
#    3        b   urgent_s         2
#    4        b   urgent_s         2
#    5        c  bthd_sell         1
#    6        c  bthd_sell         1
#    7        c  christmas
#    8        c  christmas

demo

yumi1043 iT邦新手 5 級 ‧ 2020-08-21 22:44:27 檢舉

謝謝listennn08大的解答還有提供我相關的文章 感謝!!! 祝您周末愉快

3
張小馬~
iT邦新手 3 級 ‧ 2020-08-21 21:39:14

同樣身為先學SQL再學Python的路過~幫樓上改兩處:

df.groupby('memberid',as_index=False).nth(-2)
多了【as_index=False】,對學SQL的來說,看上去肯定舒服多了,哈哈~

另外建議.dropna()不要放,SQL裡縱使對應到的是null,groupby後一樣會秀出(縱使本案例沒有這機會),真要排除也是寫在where(在python則是另寫loc條件),資料處理的順序上,不會在groupby的時候就drop掉(where掉)資料。

...... 'urgent_s', 2, None))
我看原po說他要null,不要給他空白,null是很特別的存在,沒有人可以取代的(吶喊~~)。

另外第二點啊,python沒有直接case when的概念,概念上是反正你先隨便建出一欄(最好是你原本ELSE要寫的內容),然後再下條件去改。當然寫成樓上那樣比較像是Python慣用者會寫的樣子,只是SQL背景的,應該會比較喜歡寫成如下圖那樣。有點像是SQL中把ELSE搬到第一條先寫好,再寫各種when。
不過還是要注意,Python這指令是彼此獨立的,不像SQL的case when是整包一起,所以如果你的when條件彼此有交集,要留意Python後面的指令,會改到前面的,和SQL中case前面的when可以依序先把想要的挑出來,剩下來的繼續when的概念,還是有所不同。

https://ithelp.ithome.com.tw/upload/images/20200821/20111566KWQIt7r446.png

yumi1043 iT邦新手 5 級 ‧ 2020-08-21 22:48:15 檢舉

感謝小馬大。謝謝在禮拜五晚上還抽空回文 原本想說明天起來看的 現在看到太興奮來研究一下 非常感謝!!! 我原本一直覺得Sql條件篩選有點太方便了 到現在一直會有點困擾 現在看來只是我python不夠熟 會再多研究一點 感謝 祝您周末愉快

不用那麼客氣啦~ /images/emoticon/emoticon37.gif

因為當初自己從SQL背景要來學Python,自覺是蠻...痛苦的,哈哈~順便補充我當初寫groupby的筆記,縱使現在我Python要寫groupby還是得回頭複製筆記來寫,空手寫不出,光那個大中小括號就搞死我了。(我還是比較喜歡SQL...)

https://ithelp.ithome.com.tw/upload/images/20200822/201115669f1UCoQTtq.png

2
I code so I am
iT邦高手 1 級 ‧ 2020-08-22 11:32:00

map 也可以使用函數轉換資料,如下:

import pandas as pd
import numpy as np

df = pd.DataFrame(
  np.array([
    ["a", "2020-08-05"], 
    ["a", "2020-08-12"],
    ["a", "2020-08-17"],
    ["b", "2020-08-16"],
    ["b", "2020-08-19"],
    ["c", "2020-05-01"],
    ["c", "2020-05-03"],
    ["c", "2020-05-04"],
    ["c", "2020-05-07"]]),
  columns=["memberid", "order_date"]
)
print(df.groupby('memberid').nth(-2).dropna())

#              order_date
#    memberid
#    a         2020-08-12
#    b         2020-08-16
#    c         2020-05-04


df1 = pd.DataFrame(
  np.array([
    ["a", "bthd"],
    ["a", "bthd_sell"],
    ["a", "urgent_s"],
    ["b", "urgent_s"],
    ["b", "urgent_s"],
    ["c", "bthd_sell"],
    ["c", "bthd_sell"],
    ["c", "christmas"],
    ["c", "christmas"]]),
  columns=["memberid","campaign"]
)

def generate_label(x):
    if x == 'bthd_sell':
        return 1
    elif x == 'urgent_s':
        return 2
    else: return None


df1['cam_label'] = df1['campaign'] .map(generate_label)
df1
yumi1043 iT邦新手 5 級 ‧ 2020-08-22 17:14:02 檢舉

感謝I code so I am大! 最近一直map(dict)導致陷入這個思考出不來 謝謝這個方法!!

我要發表回答

立即登入回答