【问题标题】:Using `itertools` to combine DataFrame columns使用 `itertools` 组合 DataFrame 列
【发布时间】:2022-01-12 20:39:43
【问题描述】:

我有一个DataFrame,它看起来像这个玩具示例:

import pandas as pd
df = np.array([
    [20.078,19.679,19.585,19.406,19.37,14.97,13.992,20.122,20.736],
    [20.443,19.115,18.918,18.749,18.698,14.638,14.041,21.646,21.456],
    [19.723,19.593,19.353,19.175,19.258,15.193,14.354,21.122,21.09],
    [19.683,19.393,19.273,18.995,18.95,15.545,14.53,22.465,20.091],
    [19.769,19.233,19.083,18.983,18.768,14.978,14.224,21.684,20.314],
    [19.908,19.5,19.065,18.838,18.354,13.837,13.016,21.307,21.234]
])

df = pd.DataFrame(df, columns = ['u', 'g', 'r', 'i', 'zmag', 'W1', 'W2', 'NUV', 'FUV'])

我想将列成对组合成减法组合,这就是 sn-p 所做的:

df['FUV_NUV'] = dataset['FUV'] - dataset['NUV']
df['FUV_u'] = df['FUV'] - df['u']
df['u_g'] = df['u'] - df['g']
df['g_r'] = df['g'] - df['r']
df['r_i'] = df['r'] - df['i']
df['i_z'] = df['i'] - df['zmag']
df['z_W1'] = df['zmag'] - df['W1']
df['W1_W2'] = df['W1'] - df['W2']

当然,有一个更好的方法可以做到这一点,我发现了here

combs = list(chain.from_iterable(combinations(df.columns, i)
                                 for i in range(2, len(df.columns) + 1)))
for cols in combs:
    df['_'.join(cols)] = df.loc[:, cols].sum(axis=1)

但是,这会产生所有个组合(例如u+g+W1+W2+...)。

我怎样才能改变它,以便它

  1. 遍历列以产生最大两列的所有组合(例如:u-g、u-r、u-i、u-zmag...)
  2. 减法(即不是sum)?

【问题讨论】:

  • "遍历列以产生最大两列的所有组合" 提示 1:您认为 for i in range(2, len(df.columns) + 1) 部分是什么意思?提示 2:查看您引用的页面上问题中的代码
  • “减法(即不是总和)?”好吧,你试过把pandas difference of columnsinto a search engine放进去吗?

标签: python arrays pandas iteration


【解决方案1】:

您可以使用此列表推导生成列表,由相邻列的 2 个元素组合并环绕 然后你可以通过遍历这个列表来生成额外的列

comb = [(x, df.columns[(i+1) % len(df.columns)]) for i, x in enumerate(df.columns)]


for x, y in comb:
  df[f'{x}_{y}'] = df[x] - df[y]

这会产生输出:

        u       g       r       i    zmag      W1      W2     NUV     FUV    u_g    g_r    r_i  i_zmag  zmag_W1  W1_W2  W2_NUV  NUV_FUV  FUV_u
0  20.078  19.679  19.585  19.406  19.370  14.970  13.992  20.122  20.736  0.399  0.094  0.179   0.036    4.400  0.978  -6.130   -0.614  0.658
1  20.443  19.115  18.918  18.749  18.698  14.638  14.041  21.646  21.456  1.328  0.197  0.169   0.051    4.060  0.597  -7.605    0.190  1.013
2  19.723  19.593  19.353  19.175  19.258  15.193  14.354  21.122  21.090  0.130  0.240  0.178  -0.083    4.065  0.839  -6.768    0.032  1.367
3  19.683  19.393  19.273  18.995  18.950  15.545  14.530  22.465  20.091  0.290  0.120  0.278   0.045    3.405  1.015  -7.935    2.374  0.408
4  19.769  19.233  19.083  18.983  18.768  14.978  14.224  21.684  20.314  0.536  0.150  0.100   0.215    3.790  0.754  -7.460    1.370  0.545
5  19.908  19.500  19.065  18.838  18.354  13.837  13.016  21.307  21.234  0.408  0.435  0.227   0.484    4.517  0.821  -8.291    0.073  1.326

【讨论】:

  • 如何确保生成所有可能的非重复二元组合?例如,u_zmagW2_i 但不是 i_W2 ?
  • 你想要所有的 2 元素组合吗?
  • 理想情况下,是的,但不重复。
  • @Jim421616,我不太清楚你想要什么。你能用你期望给定这个数据框的组合来更新问题吗?
【解决方案2】:

试用df.diff(axis=1) 并查看函数的documentation

计算一个Dataframe元素与Dataframe中另一个元素的差异(默认是前一行的元素)。

当我们使用axis=1 时,该函数获取一列与上一列之间的差异。因此,您可能需要重新排序列才能使此功能正常工作。


这是另一个使用循环的选项。

在我看来,使用itertools 的方法比简单地写出要减去的列可读性差。

我还建议在数据帧上设置数据时使用df.loc[] 语法。

pairs = [
    ("FUV", "NUV"),
    ("FUV", "u"),
    ("u", "g"),
    ("g", "r"),
    ("r", "i"),
    ("i", "zmag"),
    ("zmag", "W1"),
    ("W1", "W2"),
]

for col1, col2 in pairs:
    new_col_name = f"{col1}_{col2}"
    df.loc[:, new_col_name] = df[col1] - df[col2]

【讨论】:

    猜你喜欢
    • 2020-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多