在操作现有列时基于现有列的多个条件创建新列

2024-05-15 23:02:41 发布

您现在位置:Python中文网/ 问答频道 /正文

我是来自R背景的Python/pandas新手。我很难理解如何根据现有列的多个条件操纵现有列以创建新列。有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”对象

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

我知道我可能有一些术语或概念不正确,并表示歉意,但是我看到的关于创建一个具有多个条件的新列的答案似乎不是在操纵他们正在检查条件的现有列,而是简单地接受一个赋值。我只能想象,有一种更有效的方法可以做到这一点,即不太“R-ey”,但我不知道从哪里开始


Tags: formatpandasdfdatetimedateasdt条件
2条回答

除非有人告诉我,否则我会这样做。如果有一种方法可以实现矢量化(或者只是一种更好的方法),我将不胜感激

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

这并不是一个完整的答案,正如插图说明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)

一般来说,矢量化比在行上循环要好,因为循环是在一个更“低”的级别上完成的,而且效率更高

相关问题 更多 >