【问题标题】:Compute numeric value using string response by evaluating numeric and string values in logical function通过评估逻辑函数中的数值和字符串值,使用字符串响应计算数值
【发布时间】:2021-07-27 20:12:28
【问题描述】:

我正在尝试编写一个函数,该函数在“频率”列中获取字符串响应并计算某人每年饮酒的总天数。

我试图从字符串中获取的三个主要值是语句中存在的数字和单词(周、月、年),用于计算某人一年内饮酒的平均总天数。例如,如果某人每月喝 2-3 次,则等式将是 (2+3/2)*12 = 每年 30 次。下面的数据表显示了数据的示例。

Frequency
1 day per month
3 days per week
1 to 2 days per year
2 days per week
1 day per month
6-11 days per year
5-6 days a week

我正在尝试制作的表格将具有每年的平均天数,如下所示:

Frequency per year
12
156
1.5
104
12
8.5
286

到目前为止,我已经编写了以下代码:

import pandas as pd 
AlcData = pd.read_excel('Alcohol_Data.xlsx')

#add new column with unittime value for use in function 
AlcData['unittime'] = AlcData.Frequency.str.extract(r'\b(\w+)$', 
                                     expand = True)

def calculatetotaldays(row):
    for x in range(1,11):
#read in row item as string value 
        string = AlcData.Frequency
# create list of number values from the string
        numbers = [int(i) for i in string.split() if i.isdigit()]
 #compute total days if list has length of 1 
    if len(numbers) == 1:
         x = [numbers[j] for j in (0)]
    if row[AlcData.unittime] == 'week': 
        total = x*52
    elif row[AlcData.unittime] == 'month':
        total = x*12
    elif row[AlcData.unittime] == 'year': 
        total = x
#compute total days if list has length of 2 
    if len(numbers) == 2:
        x, y = [numbers[j] for j in (0, 1)]
    if row[AlcData.unittime] == 'week': 
        total = (((x+y)/2)*52)
    elif row[AlcData.unittime] == 'month': 
        total = (((x+y)/2)*12)
    elif row[AlcData.unittime] == 'year': 
        total = ((x+y)/2)
    return total

AlcData['totalperyear'] = AlcData.apply(calculatetotaldays, axis=1)

我目前收到错误消息:“'Series' 对象没有属性 'split'”,同时尝试将行中的数字提取到列表中。有谁知道如何在函数中纠正这个错误?更重要的是,这种方法(使用列表的长度来分配这些变量并计算数字)是解决这个问题的最佳方法吗?

我已经为此苦苦挣扎了很长时间,因此有关如何计算此信息的任何和所有提示都会非常有帮助。

【问题讨论】:

  • 为什么在 "range(1, 11)" 上有一个 for 循环?
  • @MichaelButscher 因为任何字符串响应中的最高数字是 11,最低数字是 1。不过我不确定这是否正确

标签: python string dataframe function logic


【解决方案1】:

这在很大程度上是一个重写,但这里有一个方法来解决它只需要pandas

In [92]: (
    ...:     df['Frequency']
    ...:     .str.split()
    ...:     .str[-1].map({'week': 52, 'month': 12, 'year': 1})
    ...:     .mul(
    ...:         df['Frequency']
    ...:         .str.extract(r'(\d+)\D*(\d+)?')
    ...:         .ffill(axis=1)
    ...:         .astype(int).mean(axis=1)
    ...:     )
    ...: )
Out[92]:
0     12.0
1    156.0
2      1.5
3    104.0
4     12.0
5      8.5
6    286.0
dtype: float64

我们可以将其分解为数值部分的计算,然后是乘数。您可以使用类似于您之前所做的正则表达式来获取数字:

In [89]: df['Frequency'].str.extract(r'(\d+)\D*(\d+)?')
Out[89]:
   0    1
0  1  NaN
1  3  NaN
2  1    2
3  2  NaN
4  1  NaN
5  6   11
6  5    6

从那里,您可以使用.ffill().mean() 将其变成一个数字:

In [90]: df['Frequency'].str.extract(r'(\d+)\D*(\d+)?').ffill(axis=1).astype(int).mean(axis=1)
Out[90]:
0    1.0
1    3.0
2    1.5
3    2.0
4    1.0
5    8.5
6    5.5
dtype: float64

如果您知道它总是以 yearmonthweek 结尾,您可以选择它并使用 map 作为乘数:

In [91]: df['Frequency'].str.split().str[-1].map({'week': 52, 'month': 12, 'year': 1})
Out[91]:
0    12
1    52
2     1
3    52
4    12
5     1
6    52
Name: Frequency, dtype: int64

然后你可以像我上面那样将它们相乘。

【讨论】:

    猜你喜欢
    • 2020-07-27
    • 2012-01-12
    • 2023-04-10
    • 2020-02-18
    • 1970-01-01
    • 2021-04-27
    • 2020-03-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多