在处理现有列的同时,根据现有列的多种条件创建新列

时间:2020-09-29 18:26:47

标签: python pandas dataframe

我是R背景的Python /熊猫新手。我在理解如何处理现有列以根据现有列的多个条件创建新列时遇到麻烦。有10个不同的条件需要满足,但为简单起见,我将使用2种情况。

在R中:

install.packages("lubridate")
library(lubridate)

df <- data.frame("Date" = c("2020-07-01", "2020-07-15"))
df$Date <- as.Date(df$Date, format = "%Y-%m-%d")

df$Fiscal <- ifelse(day(df$Date) > 14, 
                paste0(year(df$Date),"-",month(df$Date) + 1,"-01"),
                paste0(year(df$Date),"-",month(df$Date),"-01")
              )
df$Fiscal <- as.Date(df$Fiscal, format = "%Y-%m-%d")

在Python中,我有:

import pandas as pd
import datetime as dt

df = {'Date': ['2020-07-01', '2020-07-15']}
df = pd.DataFrame(df)

df['Date'] = pd.to_datetime(df['Date'], yearfirst = True, format = "%Y-%m-%d")

df.loc[df['Date'].dt.day > 14, 
       'Fiscal'] = "-".join([dt.datetime.strftime(df['Date'].dt.year), dt.datetime.strftime(df['Date'].dt.month + 1),"01"])

df.loc[df['Date'].dt.day <= 14, 
       'Fiscal'] = "-".join([dt.datetime.strftime(df['Date'].dt.year), dt.datetime.strftime(df['Date'].dt.month),"01"])

如果我不转换'Date'字段,它说它期望一个字符串,但是,如果我确实转换了date字段,我仍然会收到错误,因为它似乎适用于'Series'对象。 / p>

TypeError: descriptor 'strftime' for 'datetime.date' objects doesn't apply to a 'Series' object

我知道我可能有一些术语或概念不正确并表示歉意,但是我看到的关于创建具有多个条件的新列的答案似乎并没有操纵他们正在检查条件的现有列,而只是根据指定的值。我只能想象有一种更有效的方法来减少“ R-ey”,但是我不确定从哪里开始。

2 个答案:

答案 0 :(得分:1)

这并不是一个完整的答案,就像{em>插图 strftime的工作原理一样:strftimedate(time)对象的一种方法,它采用格式字符串作为参数:

import pandas as pd
import datetime as dt

df = {'Date': ['2020-07-01', '2020-07-15']}
df = pd.DataFrame(df)
df['Date'] = pd.to_datetime(df['Date'], yearfirst = True, format = "%Y-%m-%d")

s = [dt.date(df['Date'][i].year, df['Date'][i].month + 1, 1).strftime('%Y-%m-%d')
     for i in df['Date'].index]

print(s)

结果:

['2020-08-01', '2020-08-01']

再次:没有完整的答案,只是一个提示。

编辑:您可以对此进行矢量化,例如:

import pandas as pd
import datetime as dt

df = {'Date': ['2020-07-01', '2020-07-15']}
df = pd.DataFrame(df)
df['Date'] = pd.to_datetime(df['Date'], yearfirst=True, format='%Y-%m-%d')

df['Fiscal'] = df['Date'].apply(lambda d: dt.date(d.year, d.month, 1)
                                          if d.day < 15 else
                                          dt.date(d.year, d.month + 1, 1))
print(df)

结果:

        Date      Fiscal
0 2020-07-01  2020-07-01
1 2020-07-15  2020-08-01

这里我正在使用即时lambda函数。您也可以使用外部定义的函数来做到这一点:

def to_fiscal(date):
    if date.day < 15:
        return dt.date(date.year, date.month, 1)
    return dt.date(date.year, date.month + 1, 1)

df['Fiscal'] = df['Date'].apply(to_fiscal)

通常,矢量化比循环遍历更好,因为循环是在“更低”的水平上完成的,并且效率更高。

答案 1 :(得分:0)

直到有人告诉我,否则我将以这种方式进行。如果有一种方法可以将其向量化(或者通常来说是一种更好的方法),我将不胜感激

import pandas as pd
import datetime as dt

df = {'Date': ['2020-07-01', '2020-07-15']}
df = pd.DataFrame(df)

df['Date'] = pd.to_datetime(df['Date'], yearfirst=True, format='%Y-%m-%d')

test_list = list()
for i in df['Date'].index:
   
    mth = df['Date'][i].month
    yr = df['Date'][i].year
    dy = df['Date'][i].day
    
    if(dy > 14):
        new_date = dt.date(yr, mth + 1, 1)
    else:
        new_date = dt.date(yr, mth, 1)
      
    test_list.append(new_date)
    
df['New_Date'] = test_list