【问题标题】:How to create new columns in pandas dataframe with ONLY a list-comprehension?如何仅使用列表理解在 pandas 数据框中创建新列?
【发布时间】:2020-09-06 09:59:46
【问题描述】:

我想在 DataFrame 中创建一组 n 列,每个列使用列表推导分配一个单独的值。

#My original dataframe
df = pd.DataFrame({'A':[1,2,3],'B':[4,5,6]})

   A  B
0  1  4
1  2  5
2  3  6
#Expected output - 

pd.concat([df, pd.DataFrame(np.tile(np.array([5,10,15,20,25])[:,None], 3).T)], axis=1)

   A  B  0   1   2   3   4
0  1  4  5  10  15  20  25
1  2  5  5  10  15  20  25
2  3  6  5  10  15  20  25

我需要以这种方式进行 -

#ROUGH structure of the code that I am looking for -
n = "number of columns i want to add"
df[[i for i in range(n)]] = numpyarray #whose shape is (n,3)

我面临的错误很明显-

KeyError: "None of [Int64Index([0, 1, 2], dtype='int64')] are in the [columns]"

#AND

SyntaxError: can't assign to list comprehension

我已经阅读了其他允许添加多列的解决方案,但这个解决方案特别需要一个带有 n 迭代器的循环,因为 -

  1. 数据框可能需要添加 25 列,这不依赖于值数组
  2. 值数组可以是 (3, 15),这意味着最后 10 列不会从数组中获取它们的值
  3. 首选的解决方案是列表推导,因为我将创建的列列表(例如 25 个)来自基于列表推导的迭代器

【问题讨论】:

  • 你不能按你的要求去做。 Pandas 不允许一次创建多个列。
  • 这是一个答案。但我仍然不确定为什么我的问题已关闭。
  • related ,如果使用循环,可能你可以考虑不转置数组,然后 zip 和迭代 +assign ,类似arr = np.tile(np.array([5,10,15,20,25])[:,None], 3)for a,b in zip(range(5),arr): df[a] = b
  • @AkshaySehgal 我猜您需要形状数组 (3, n)...因为您要分配 n
  • @anky 我浏览了那篇文章,虽然其中大部分对我有用,但问题是我不知道我需要添加多少列。此外,将用于分配值的数组可能表示也可能不表示数据框将具有的列数。因此,如果数组为 (3,10),则可能仅填充数据帧的前 10 个新生成的列,而另外 5 个列仍为 Nan。

标签: python pandas dataframe list-comprehension


【解决方案1】:

这是解决方案的更新版本。

import pandas as pd
import numpy as np
df = pd.DataFrame({'A':[1,2,3],'B':[4,5,6]})
print(df)
n = 10

df = pd.concat([df,pd.DataFrame(
    np.tile([5*(i+1) for i in range(n)],len(df)).reshape(len(df),n),
    columns=[i+1 for i in range (n)])],axis=1)

print(df)

由此产生的输出如下:

原始数据框:

   A  B
0  1  4
1  2  5
2  3  6

合并的数据框

   A  B  1   2   3   4   5   6   7   8   9  10
0  1  4  5  10  15  20  25  30  35  40  45  50
1  2  5  5  10  15  20  25  30  35  40  45  50
2  3  6  5  10  15  20  25  30  35  40  45  50

我们需要得到一个包含值[5,10,15,...,n*5] 的表。为此,我正在使用:

np.tile([5*(i+1) for i in range(n)],len(df))

这会给我一个这样的数组:

array([ 5, 10, 15, 20, 25, 30, 35, 40, 45, 50,  5, 10, 15, 20, 25, 30, 35,
       40, 45, 50,  5, 10, 15, 20, 25, 30, 35, 40, 45, 50])

现在我们需要将其切换为 3 行 n 列,在本例中 n=10。我正在这样做:

reshape(len(df),n)

这里 len(df) = 3 和 n = 10

结果

np.tile([5*(i+1) for i in range(n)],len(df)).reshape(len(df),n)

将是:

array([[ 5, 10, 15, 20, 25, 30, 35, 40, 45, 50],
       [ 5, 10, 15, 20, 25, 30, 35, 40, 45, 50],
       [ 5, 10, 15, 20, 25, 30, 35, 40, 45, 50]])

现在我已经列出了值,我只需要获取列名。我正在使用列表推导来创建列名。

columns=[i+1 for i in range (n)])]

显然我们必须使用axis=1,否则它将无法正确连接。

将所有这些放在一起即可得到最终结果集。

我回去尝试使用 Akshay 的逻辑。这是我得到的。这也有效。

df2 = pd.concat([df,pd.DataFrame(
    np.tile(np.array([[5*i] for i in range(1,n+1)]), len(df)).T,
    columns=[i+1 for i in range (n)])],axis=1)
print(df2)

如果您认为有更简单的方法可以做到这一点,请告诉我,以便我也可以学习。

之前的回复如下:

我对 pandas 还很陌生,仍在学习解决问题。这是我尝试过的,看起来这就是你想要的。

import pandas as pd
df = pd.DataFrame({'A':[1,2,3],'B':[4,5,6]})
lst = [5,10,15,20,25]
n = 6
for i in range(1,n): df[i] =lst[i-1]
print(df)

这给了我以下输出:

   A  B  1   2   3   4   5
0  1  4  5  10  15  20  25
1  2  5  5  10  15  20  25
2  3  6  5  10  15  20  25

这有意义吗?这是您要找的吗?

【讨论】:

  • 这对我有用,谢谢!但我正在寻找一个专门的列表理解。
  • @AkshaySehgal,我想通了,但有点冗长。查看我的新回复。
【解决方案2】:

通过列表理解创建列的一个想法,在 pandas 1.1.1 中进行了测试:

df = pd.DataFrame({'A':[1,2,3],'B':[4,5,6]})

#list created by list comprehension
L = [i + 1 for i in range(5)]
print (L)
[1, 2, 3, 4, 5]

n = len(L)
df[list(range(n))] = L

print (df)
   A  B  0  1  2  3  4
0  1  4  1  2  3  4  5
1  2  5  1  2  3  4  5
2  3  6  1  2  3  4  5

【讨论】:

  • 有趣的是我想出了同样的答案。 :)
  • @JoeFerndz - 嗯,我认为它不同,我分配列表 L 没有 for 循环。
  • 遗憾的是,这对我不起作用 (pd.__version__ = 1.0.3)。引发错误 - KeyError: "None of [Int64Index([0, 1, 2, 3, 4], dtype='int64')] are in the [columns]"。想知道 pandas 发生了什么变化以允许此功能会很有趣。
  • @AkshaySehgal - 2 个想法 - 如何预先分配值,例如 df[list(range(n))] = 1 然后 df[list(range(n))] = L ?另一个想法是df.loc[:, list(range(n))] = L
  • 看我的迭代器是函数的输出
猜你喜欢
  • 2019-12-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-21
  • 2016-05-12
  • 1970-01-01
相关资源
最近更新 更多