![](/img/trans.png)
[英]How to append a "Total" row to pandas dataframe with MultiIndex
[英]Pandas: append row to DataFrame with multiindex in columns
我有一個 DataFrame,在列中有一個多索引,並且想使用字典來 append 新行。
假設 DataFrame 中的每一行都是一個城市。 列包含“距離”和“車輛”。 每個單元格都是在這段距離內選擇這輛車的人口百分比。
我正在構建這樣的索引:
index_tuples=[]
for distance in ["near", "far"]:
for vehicle in ["bike", "car"]:
index_tuples.append([distance, vehicle])
index = pd.MultiIndex.from_tuples(index_tuples, names=["distance", "vehicle"])
然后我正在創建一個 dataframe:
dataframe = pd.DataFrame(index=["city"], columns = index)
dataframe 的結構看起來不錯。 雖然pandas已經添加了Nans作為默認值?
現在我想為新城市建立一個字典並添加它:
my_home_city = {"near":{"bike":1, "car":0},"far":{"bike":0, "car":1}}
dataframe["my_home_city"] = my_home_city
但這失敗了:
ValueError:值的長度與索引的長度不匹配
這是完整的錯誤消息(pastebin)
更新:
謝謝你所有的好答案。 恐怕我在我的例子中把問題簡單化了。 實際上我的索引嵌套了 3 個級別(而且它可能會變得更多)。
所以我接受了將我的字典轉換為元組列表的通用答案。 這可能不如其他方法干凈,但適用於任何多索引設置。
你可以像這樣附加到你的數據幀:
my_home_city = {"near":{"bike":1, "car":0},"far":{"bike":0, "car":1}}
dataframe.append(pd.DataFrame.from_dict(my_home_city).unstack().rename('my_home_city'))
輸出:
distance near far
vehicle bike car bike car
city NaN NaN NaN NaN
my_home_city 1 0 0 1
關鍵是要與創建數據框行from_dict
然后unstack
,讓您的數據幀原來多指標與柱的結構,然后rename
獲得指數和append
。
或者,如果您不想首先創建空數據框,則可以使用此方法使用新數據創建數據框。
pd.DataFrame.from_dict(my_home_city).unstack().rename('my_home_city').to_frame().T
輸出:
far near
bike car bike car
my_home_city 0 1 1 0
解釋:
pd.DataFrame.from_dict(my_home_city)
far near
bike 0 1
car 1 0
現在,讓我們重新創建多索引並將新數據幀轉換為原始數據幀的結構。
pd.DataFrame.from_dict(my_home_city).unstack()
far bike 0
car 1
near bike 1
car 0
dtype: int64
我們使用重命名為該系列賦予一個名稱,該名稱在附加到原始數據幀時成為該數據幀行的索引標簽。
far bike 0
car 1
near bike 1
car 0
Name: my_home_city, dtype: int64
現在,如果您將該系列轉換為一個幀並進行轉置,它看起來非常像一個新行,但是,沒有必要這樣做,因為Pandas執行內部數據對齊,因此將此系列追加到數據幀將自動對齊和添加新的數據幀記錄。
dataframe.append(pd.DataFrame.from_dict(my_home_city).unstack().rename('my_home_city'))
distance near far
vehicle bike car bike car
city NaN NaN NaN NaN
my_home_city 1 0 0 1
多索引是一個tuple
list
,我們只需要修改你的dict
,然后我們可以直接賦值
d = {(x,y):my_home_city[x][y] for x in my_home_city for y in my_home_city[x]}
df.loc['my_home_city',:]=d
df
Out[994]:
distance near far
vehicle bike car bike car
city NaN NaN NaN NaN
my_home_city 1 0 0 1
更多信息
d
Out[995]:
{('far', 'bike'): 0,
('far', 'car'): 1,
('near', 'bike'): 1,
('near', 'car'): 0}
df.columns.values
Out[996]: array([('near', 'bike'), ('near', 'car'), ('far', 'bike'), ('far', 'car')], dtype=object)
我認為您甚至不需要初始化空數據幀。 使用你的d
,我可以使用unstack
和轉置獲得你想要的輸出:
pd.DataFrame(d).unstack().to_frame().T
far near
bike car bike car
0 0 1 1 0
使用MultiIndex.from_product
初始化空數據幀。
distances = ['near', 'far']
vehicles = ['bike', 'car']
df = pd.DataFrame([], columns=pd.MultiIndex.from_product([distances, vehicles]),
index=pd.Index([], name='city'))
您的字典會生成方形矩陣(車輛距離),因此將其to_frame
堆疊(將生成一個系列),然后通過使用相關城市名稱調用( to_frame
)並將列轉換為行來將其轉換為數據幀行。
>>> df.append(pd.DataFrame(my_home_city).unstack().to_frame('my_home_city').T)
far near
bike car bike car
city
my_home_city 0 1 1 0
只是為了添加所有答案,這只是另一個(可能沒有太大不同)簡單示例,以更可重現的方式表示:
import itertools as it
from IPython.display import display # this is just for displaying output purpose
import numpy as np
import pandas as pd
col_1, col_2 = ['A', 'B'], ['C', 'D']
arr_size = len(col_2)
col = pd.MultiIndex.from_product([col_1, col_2])
tmp_df = pd.DataFrame(columns=col)
display(tmp_df)
for s in range(3):# no of rows to add to tmp_df
tmp_dict = {x : [np.random.random_sample(1)[0] for i in range(arr_size)] for x in range(arr_size)}
tmp_ser = pd.Series(it.chain.from_iterable([tmp_dict[x] for x in tmp_dict]), index=col)
# display(tmp_dict, tmp_ser)
tmp_df = tmp_df.append(tmp_ser[tmp_df.columns], ignore_index=True)
display(tmp_df)
上面的一些注意事項:
len(col_1)*len(col_2)
,即構成多索引的元素長度的乘積。list(it.chain.from_iterable([[2, 3], [4, 5]]))
只是這樣做 [2,3,4,5]d = dict() for g in predictor_types: for col in predictor_types[g]: tot = len(ames) - ames[col].count() if tot: d.setdefault('type',[]).append(g) d.setdefault('predictor',[]).append(col) d.setdefault('missing',[]).append(tot) pd.DataFrame(d).set_index(['type','predictor']).style.bar(color='DodgerBlue')
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.