Ниже приведен кадр данных панд:
cluster Value
1 A
1 NaN
1 NaN
1 NaN
1 NaN
2 NaN
2 NaN
2 B
2 NaN
3 NaN
3 NaN
3 C
3 NaN
4 NaN
4 S
4 NaN
5 NaN
5 A
5 NaN
5 NaN
Если мы рассмотрим данные, кластер 1 имеет значение "A" для одной строки и останется неизменным. Я хочу заполнить значение "А" для всех строк кластера 1. Аналогично для всех кластеров. Основываясь на одном из значений кластера, я хочу заполнить оставшиеся строки кластера. Выход должен быть похож,
cluster Value
1 A
1 A
1 A
1 A
1 A
2 B
2 B
2 B
2 B
3 C
3 C
3 C
3 C
4 S
4 S
4 S
5 A
5 A
5 A
5 A
Я новичок в python и не знаю, как это сделать. Может ли кто-нибудь помочь в этом?
редактировать
Следующее выглядит лучше:
nan_map = df.dropna().set_index('cluster').to_dict()['Value']
df['Value'] = df['cluster'].map(nan_map)
print(df)
оригинал
Я не могу придумать лучшего способа сделать это, чем перебирать все строки, но может существовать. Сначала я создал свой DataFrame:
import pandas as pd
import math
# Build your DataFrame
df = pd.DataFrame.from_items([
('cluster', [1,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,5,5,5,5]),
('Value', [float('nan') for _ in range(20)]),
])
df['Value'] = df['Value'].astype(object)
df.at[ 0,'Value'] = 'A'
df.at[ 7,'Value'] = 'B'
df.at[11,'Value'] = 'C'
df.at[14,'Value'] = 'S'
df.at[17,'Value'] = 'A'
Теперь вот подход, который сначала создает dict nan_map
, затем устанавливает значения в Value
как указано в dict.
# Create a dict to map clusters to unique values
nan_map = df.dropna().set_index('cluster').to_dict()['Value']
# nan_map: {1: 'A', 2: 'B', 3: 'C', 4: 'S', 5: 'A'}
# Apply
for i, row in df.iterrows():
df.at[i,'Value'] = nan_map[row['cluster']]
print(df)
Выход:
cluster Value 0 1 A 1 1 A 2 1 A 3 1 A 4 1 A 5 2 B 6 2 B 7 2 B 8 2 B 9 3 C 10 3 C 11 3 C 12 3 C 13 4 S 14 4 S 15 4 S 16 5 A 17 5 A 18 5 A 19 5 A
Примечание. Это устанавливает все значения на основе кластера и не проверяет наличие NaN-ness. Вы можете поэкспериментировать с чем-то вроде:
# Apply
for i, row in df.iterrows():
if isinstance(df.at[i,'Value'], float) and math.isnan(df.at[i,'Value']):
df.at[i,'Value'] = nan_map[row['cluster']]
чтобы увидеть, какая из них эффективнее (моя догадка - первая, без проверок).
groupby
+ bfill
и ffill
df = df.groupby('cluster').bfill().ffill()
df
cluster Value
0 1 A
1 1 A
2 1 A
3 1 A
4 1 A
5 2 B
6 2 B
7 2 B
8 2 B
9 3 B
10 3 B
11 3 C
12 3 C
13 4 S
14 4 S
15 4 S
16 5 A
17 5 A
18 5 A
19 5 A
Или же,
groupby
+ transform
с first
df['Value'] = df.groupby('cluster').Value.transform('first')
df
cluster Value
0 1 A
1 1 A
2 1 A
3 1 A
4 1 A
5 2 B
6 2 B
7 2 B
8 2 B
9 3 B
10 3 B
11 3 C
12 3 C
13 4 S
14 4 S
15 4 S
16 5 A
17 5 A
18 5 A
19 5 A