Mam dataframe w Pythonie, który ma kolumnę prowadzącą różnicę 2 dat. Chciałbym utworzyć nową / nadpisaną na istniejącą kolumnę, która może konwertować numeryczne do zmiennej kategorycznej na podstawie poniższych zasad:

difference              0 days    Level 0
difference              2 days    Level 1
difference              2-6 days  Level 2
difference             6-15 days  Level 3
difference             15-69 days Level 4
difference             NAT        Level 5

Jak można to osiągnąć.

2
user4943236 26 czerwiec 2017, 08:04

4 odpowiedzi

Najlepsza odpowiedź

Powiedz, że nazwa kolumny jest "różnica"

Możesz zdefiniować metodę

def get_difference_category(difference):
    if difference < 0:
        return 0
    if difference <=2:
        return 1
    #.. and so on

df['difference'] = df['difference'].apply(lambda value: get_difference_category(value), axis=1)

Linki odniesienia: https://github.com/vi3k6i5/pandas_basics/blob/master/2_b_apply_a_function_Row_Wise. IPYNB.

https://github.com/vi3k6i5/pandas_basics/blob/master/2_c_apply_a_function_to_a_Column.ipynb.

2
Vikash Singh 26 czerwiec 2017, 05:26

Dodałem działkę do analizy dystrybucji. Użyłem również Dataframe i funkcję Lambda, aby uzyskać moje różnice. Wizualiza pomogą Ci zrozumieć dane. Histogram zapewnia wgląd w rozkłady klasyfikacji, a parowanie pokazuje, jak rozłożony jest interwał dnia.

column1=['2017-01-01','2017-01-01','2017-01-02','2017-01-03','2017-01-04','2017-01-05','2017-01-06','2017-01-07','2017-01-08','2017-01-09','2017-01-10']        
column2=['2017-01-01','2017-01-11','2017-03-09','2017-03-16','2017-01-10','2017-01-25','2017-01-25','2017-01-26','2017-01-15','2017-02-16','2017-01-24' ]

index=range(0,len(column1))
data={'column1':column1,'column2':column2}
df=pd.DataFrame(data, columns=['column1','column2'],index=index)
print(df.head())

differences=df.apply(lambda x: datetime.strptime(x['column2'],'%Y-%m-%d')-          datetime.strptime(x['column1'],'%Y-%m-%d'),axis=1)
differences=differences.dt.days.astype('int')
years_bins=[-1,0,2,6,15,69,np.inf]
output_labels=['level 0','level 1','level 2','level 3','level 4','level 5']    

out=pd.cut(differences,bins=years_bins,labels=output_labels)
df['differences']=differences
df['classification']=out

print(df.head())

fig, ax = plt.subplots()
ax = out.value_counts(sort=False).plot.barh(rot=0, color="b", figsize=(6,4))
ax.set_yticklabels(labels)
plt.show()
plt.hist(df['classification'], bins=6)
plt.show()

sns.distplot(df['differences'])
plt.show()
0
Golden Lion 15 wrzesień 2020, 12:51

Edytuj: Aby obsłużyć NAT, możesz użyć pd.cut:

data['Severity'] = pd.cut((data['End'] - data['Start']).dt.days,[-pd.np.inf,-1,0,2,6,15,69],labels=['Level 5', 'Level 0','Level 1','Level 2','Level 3','Level 4']).fillna('Level 5')

Przykład:

df.head(10)

       Start        End
0 2017-01-01 2017-01-11
1 2017-01-02 2017-03-09
2 2017-01-03 2017-03-16
3 2017-01-04 2017-01-10
4 2017-01-05 2017-01-25
5 2017-01-06 2017-01-25
6 2017-01-07 2017-01-26
7 2017-01-08 2017-01-15
8 2017-01-09 2017-02-16
9 2017-01-10 2017-01-24


df['Severity'] = pd.cut((df['End'] - df['Start']).dt.days,[-np.inf,0,2,6,15,69,np.inf],labels=['Level 0','Level 1','Level 2','Level 3','Level 4','Level 5'])

Wynik:

          End      Start Severity
0  2017-01-11 2017-01-01  Level 3
1  2017-03-09 2017-01-02  Level 4
2  2017-03-16 2017-01-03  Level 5
3  2017-01-10 2017-01-04  Level 2
4  2017-01-25 2017-01-05  Level 4
5  2017-01-25 2017-01-06  Level 4
6  2017-01-26 2017-01-07  Level 4
7  2017-01-15 2017-01-08  Level 3
8  2017-02-16 2017-01-09  Level 4
9  2017-01-24 2017-01-10  Level 3
1
Scott Boston 26 czerwiec 2017, 12:38

Możesz użyć np.searchsorted, aby znaleźć, gdzie każdy Delta spada w tablicę punktów przerwania. Wymieniam dowolne NaT różnice z Level 6

td = pd.to_timedelta(['0 days', '2 days', '6 days', '15 days', '69 days'])
difs = df.End.values - df.Start.values
vals = np.searchsorted(td.values, difs)
vals[pd.isnull(difs)] = 6

df = df.assign(
    Level=np.core.defchararray.add(
        'Level ', vals.astype(str)
    )
)
df

       Start        End    Level
0 2017-01-01 2017-01-11  Level 3
1 2017-01-02 2017-03-09  Level 4
2 2017-01-03 2017-03-16  Level 5
3 2017-01-04 2017-01-10  Level 2
4 2017-01-05 2017-01-05  Level 0
5 2017-01-06 2017-01-08  Level 1
6 2017-01-07 2017-01-26  Level 4
7 2017-01-08 2017-01-15  Level 3
8 2017-01-09 2017-02-16  Level 4
9 2017-01-10 2017-01-24  Level 3

konfiguracja

import pandas as pd
from io import StringIO

txt = """       Start        End
0 2017-01-01 2017-01-11
1 2017-01-02 2017-03-09
2 2017-01-03 2017-03-16
3 2017-01-04 2017-01-10
4 2017-01-05 2017-01-05
5 2017-01-06 2017-01-08
6 2017-01-07 2017-01-26
7 2017-01-08 2017-01-15
8 2017-01-09 2017-02-16
9 2017-01-10 2017-01-24"""

df = pd.read_csv(StringIO(txt), delim_whitespace=True).apply(pd.to_datetime)
1
piRSquared 26 czerwiec 2017, 07:47