也是最近的一個需求, 將一個 Excel 表, 多列轉多行, 就把那種行的, 業務人員經常搞的那種垃圾表,給它轉為咱熟悉的數據庫表的形式, 多列轉多行. 還要幫他們處理數據, 惡心得一批, 其實也不一定非要用什么 Pandas , 就循環遍歷二維數據而已, 可能是, Pandas 比較很好, 就總是會將它作為我的第一選擇, 事實證明, 它確實無敵強, 理論上能處理任何數據的騷操作.
需求
注: 寫錯字了, 木有 "兩", 就是 前 4 列, 尷尬得一批.
方案
- 讀取數據為一個數據, 用 Pandas 來讀, iloc 來索引值, 根據下標
- 兩個 for 循環, 分別代表兩個方向 (垂直 和 水平) 誰先誰后, 無所謂的, 結果不變, 只是順序變了.
- 假設我們, 外層循環為水平方向, 內層則為 垂直方向. (外層每移動 1 列, 內層則移動 n 行)
- 最后把所有的結果, 拼接起來, 存為 Excel 即可
實現
這里我用我小伙伴的代碼吧, 自己就不寫了, 寫啥代碼, 要什么自行車.. 會搬磚, 收藏, 還有模仿, 這才是代碼成功之道
核心代碼
df = pd.read_excel(file_path)
columns = df.columns.values
# 需要轉置的那部分 DF
row_n = df.shape[0] -1
col_n = df.shape[1] - 4
ret = [] # 大列表來存儲所有的
# 外層水平向右1列, 內層垂直向下遍歷移多行
for i in range(col_n):
for j in range(row_n):
# 索引取值 iloc[行索引,列索引] 即可
lst = [
# 先取前四列, j+1 是為了跳過第 2 行
df.iloc[j+1, 0], df.iloc[j+1, 1],
df.iloc[j+1, 2], df.iloc[j+1, 3],
# 再取當前列的, 前兩行, 和 對應的值 (i,j) 再來3個字段
columns[i+4], # 當前的列名, columns 是列字段列表
df.iloc[0, i+4], # 第一行,當前列的那個值, 即字段下面那個
df.iloc[j+1, i+4] # j 是不斷往下走, 邊走邊取值
]
# 每一次取值, 則作為新數據的一行
ret.append(lst)
# 最后再將這個新的二維數據變為 DataFrame, cols 自定義, 存 Excel 即可
之列來一波運行效果呀
完整代碼
import pandas as pd
def get_data(file_path):
"""將Excel讀取為DF"""
return pd.read_excel(file_path)
def col_to_row(df):
"""多行轉多列,返回轉好的二維數組"""
columns = df.columns.values
# 需要轉置的那部分 DF
row_n = df.shape[0] -1
col_n = df.shape[1] - 4
ret = []
for i in range(col_n):
for j in range(row_n):
# 索引取值 iloc[行索引,列索引] 即可
lst = [
# 先取前四列, j+1 是為了跳過第 2 行
df.iloc[j+1, 0], df.iloc[j+1, 1],
df.iloc[j+1, 2], df.iloc[j+1, 3],
# 再取當前列的, 前兩行, 和 對應的值 (i,j) 再來3個字段
columns[i+4],
df.iloc[0, i+4],
df.iloc[j+1, i+4]
]
# 每一次取值, 則作為新數據的一行
ret.append(lst)
return ret
def save_excel(d2_array, col_names, save_path):
"""將一個二維數組,拼接為DF 再存為Excel"""
pd.DataFrame(d2_array,
columns=col_names).to_excel(
save_path, index=False
)
# 主邏輯
data = get_data("D:/test_data/多列轉多行.xlsx") # 獲取數據
d2_array = col_to_row(data) # 處理數據
col_names = ['name','gender','age', 'major', 'I', 'AM', 'NB']
save_excel(d2_array, col_names, "D:/youge.xlsx") # 存儲數據
print("ok!")
然后來看一波, 結果, 從 Excel.
小結
- 行列轉換, 除了用什么 stack(), pivot, melt 之類的, 也有看需求, 暴力來循環的
- 這個案例關鍵在於, 兩個 for 循環來移動取值(下標) , 類似於, 指針移動在二維數組中
- 理解原理就行, 多搬磚和收藏點贊才是偷懶的唯一途徑