【问题标题】:In a pandas dataframe, how can I set the value of other columns based on the data from one column, without using a loop?在熊猫数据框中,如何在不使用循环的情况下根据一列的数据设置其他列的值?
【发布时间】:2021-07-21 04:21:42
【问题描述】:

我正在尝试构建一个用于线性回归的数据框。我想包括 11 个独立的“虚拟”变量,这些变量根据一年中的月份设置为 1 或 0。没有离题太远,我使用 11 个变量而不是 12 个变量,因为第 12 个月被截距捕获。

我知道使用 pandas 可以完成很多事情,而无需循环遍历整个数据帧,并且以这种方式执行操作通常比使用循环更快。

那么,是否可以从我的日期列中获取月份,并根据该月份将单独的列动态设置为 1 或 0?还是我在问一个愚蠢的问题?

编辑:我应该包含更多信息。 数据框的结构如下:

Date sku units ordered sessions conversion rate
2020/01/30 abc123 20 200 0.1
2020/01/31 abc123 10 100 0.1
2020/02/01 abc123 15 60 0.25

我想让它看起来像这样:

Date sku units ordered sessions conversion rate january february
2020/01/30 abc123 20 200 0.1 1 0
2020/01/31 abc123 10 100 0.1 1 0
2020/02/01 abc123 15 60 0.25 0 1

我目前用来完成此操作的代码是:

x = 1
while x < 12:
    month = calendar.month_name[x]
    df[month] = 0
    x += 1

for index, row in df.iterrows():
    d = row[0]
    month = d.strftime("%B")
    if not month == "December":
        df.at[index, month] = 1

    df.fillna(0, inplace=True)

只是不确定这是否是实现这一目标的最佳方式。

【问题讨论】:

  • "有可能吗?"是的,有很多方法。如果您提供一个关于您的数据集是什么样子以及您正在寻找什么结果集的最小示例,那么您更有可能获得针对您的特定案例的代码的完整答案。 Pandas/Python: Set value of one column based on value in another column
  • 嘿亨利,感谢您的回复。我继续向 OP 添加了更多细节。我认为这澄清了最初的问题。
  • 跟进问题。你的 DF 中有 12 月的值吗?您说第 12 个月“被截距捕获”,我认为这意味着 DF 不包含该月的值,但您的循环似乎过滤掉了 12 月。
  • 我只包括从 1 月到 11 月的月份。我将此数据框输入线性回归公式,月份是自变量。回归的问题是,如果您在所有 12 个月中的每个月都包含一个变量,则回归将失败,因为它无法解决截距问题。在这种情况下,当 1 月到 11 月的变量等于 0 时,计算第 12 个月。编辑:为清楚起见,我的行包含 12 月份的销售数据,但本月没有自变量。

标签: python pandas dataframe numpy datetime


【解决方案1】:

我的方法是首先使用 dt.month 获取每个月的月份数:

df['Date'].dt.month
0    1
1    1
2    2
Name: Date, dtype: int64

然后使用crosstab 和索引来获取计数列表:

pd.crosstab(
        df.index,
        df['Date'].dt.month
    )
Date   1  2
row_0      
0      1  0
1      1  0
2      0  1

然后merge回到索引上的DF:

df = (
    df.merge(pd.crosstab(
        df.index,
        df['Date'].dt.month
    ),
        left_index=True,
        right_index=True)
)

输出:

        Date     sku  units ordered  sessions  conversion rate  1  2
0 2020-01-30  abc123             20       200             0.10  1  0
1 2020-01-31  abc123             10       100             0.10  1  0
2 2020-02-01  abc123             15        60             0.25  0  1

最后,rename 列使用使用calendar api 生成的映射器:

df = df.rename(columns={month_num: calendar.month_name[month_num]
                        for month_num in range(1, 13)})

大家一起:

import pandas as pd
import calendar

df = pd.DataFrame(
    {'Date': {0: '2020/01/30', 1: '2020/01/31', 2: '2020/02/01'},
     'sku': {0: 'abc123', 1: 'abc123', 2: 'abc123'},
     'units ordered': {0: 20, 1: 10, 2: 15},
     'sessions': {0: 200, 1: 100, 2: 60},
     'conversion rate': {0: 0.1, 1: 0.1, 2: 0.25}})
df['Date'] = df['Date'].astype('datetime64[ns]')

df = (
    df.merge(pd.crosstab(
        df.index,
        df['Date'].dt.month
    ),
        left_index=True,
        right_index=True)
)

df = df.rename(columns={month_num: calendar.month_name[month_num]
                        for month_num in range(1, 13)})

print(df.to_string())

输出:

        Date     sku  units ordered  sessions  conversion rate  January  February
0 2020-01-30  abc123             20       200             0.10        1         0
1 2020-01-31  abc123             10       100             0.10        1         0
2 2020-02-01  abc123             15        60             0.25        0         1

【讨论】:

  • 这太棒了。我知道必须有一种方法可以在没有循环的情况下做到这一点。这是一些直接的 pandas-fu。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-10-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多