[英]Pandas unique values per row, variable number of columns with data
考慮下面的 dataframe:
import pandas as pd
from numpy import nan
data = [
(111, nan, nan, 111),
(112, 112, nan, 115),
(113, nan, nan, nan),
(nan, nan, nan, nan),
(118, 110, 117, nan),
]
df = pd.DataFrame(data, columns=[f'num{i}' for i in range(len(data[0]))])
num0 num1 num2 num3
0 111.0 NaN NaN 111.0
1 112.0 112.0 NaN 115.0
2 113.0 NaN NaN NaN
3 NaN NaN NaN NaN
4 118.0 110.0 117.0 NaN
假設我的索引是唯一的,我希望檢索每個索引行的唯一值,到 output 如下所示。 我希望保留空行。
num1 num2 num3
0 111.0 NaN NaN
1 112.0 115.0 NaN
2 113.0 NaN NaN
3 NaN NaN NaN
4 110.0 117.0 118.0
我有一個可行的,雖然很慢,解決方案,見下文。 output 編號順序不相關,只要所有值都顯示在最左邊的列中,而空值顯示在右邊。 我正在尋找加速代碼的最佳實踐和潛在想法。 先感謝您。
def arrange_row(row):
values = list(set(row.dropna(axis=1).values[0]))
values = [nan] if not values else values
series = pd.Series(values, index=[f"num{i}" for i in range(1, len(values)+1)])
return series
df.groupby(level=-1).apply(arrange_row).unstack(level=-1)
pd.version == '1.2.3'
將df.values
與List comprehension
和df.dropna
一起使用:
# Create a list of rows of dataframe
In [788]: l = df.values
# Use List Comprehension to remove dups from above list of lists
In [789]: l_without_dupes = [list(dict.fromkeys(i)) for i in l]
# Create a new dataframe from above list and drop the column with all NaN's
In [795]: res_df = pd.DataFrame(l_without_dupes).dropna(1, how='all')
In [796]: res_df
Out[796]:
0 1 2
0 111.0 NaN NaN
1 112.0 NaN 115.0
2 113.0 NaN NaN
3 NaN NaN NaN
4 118.0 110.0 117.0
另一種選擇,雖然更長:
outcome = (df.melt(ignore_index= False) # keep the index as a tracker
.reset_index()
# get the unique rows
.drop_duplicates(subset=['index','value'])
.dropna()
# use this to build the new column names
.assign(counter = lambda df: df.groupby('index').cumcount() + 1)
.pivot('index', 'counter', 'value')
.add_prefix('num')
.reindex(df.index)
.rename_axis(columns=None)
)
outcome
num1 num2 num3
0 111.0 NaN NaN
1 112.0 115.0 NaN
2 113.0 NaN NaN
3 NaN NaN NaN
4 118.0 110.0 117.0
如果您希望它與您的 output 完全匹配,您可以將其轉儲到 numpy,排序並返回 pandas:
pd.DataFrame(np.sort(outcome, axis = 1), columns = outcome.columns)
num1 num2 num3
0 111.0 NaN NaN
1 112.0 115.0 NaN
2 113.0 NaN NaN
3 NaN NaN NaN
4 110.0 117.0 118.0
另一種選擇是在 Pandas 中重塑之前在 numpy 中進行排序:
(pd.DataFrame(np.sort(df, axis = 1))
.apply(pd.unique, axis=1)
.apply(pd.Series)
.dropna(how='all',axis=1)
.set_axis(['num1', 'num2','num3'], axis=1)
)
num1 num2 num3
0 111.0 NaN NaN
1 112.0 115.0 NaN
2 113.0 NaN NaN
3 NaN NaN NaN
4 110.0 117.0 118.0
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.