【问题标题】:Dataframe with column of type list: Append to selected rows具有类型列表列的数据框:附加到选定的行
【发布时间】:2023-01-01 23:22:08
【问题描述】:

我有两个数据框(用下面的代码创建)作为

df1
       Fecha Vals
0 2001-01-01   []
1 2001-01-02   []
2 2001-01-03   []
3 2001-01-04   []
4 2001-01-05   []
5 2001-01-06   []
6 2001-01-07   []
7 2001-01-08   []
8 2001-01-09   []

df2
       Fecha  Vals
0 2001-01-01   0.0
1 2001-01-03   1.0
2 2001-01-05   2.0
3 2001-01-07   3.0
4 2001-01-09   4.0

我想将df2中的值附加到df1中的每个对应行以获得

df1
       Fecha Vals
0 2001-01-01   [0.0]
1 2001-01-02   []
2 2001-01-03   [1.0]
3 2001-01-04   []
4 2001-01-05   [2.0]
5 2001-01-06   []
6 2001-01-07   [3.0]
7 2001-01-08   []
8 2001-01-09   [4.0]

我即将完成 for 循环,但对于大型数据帧,我的部分工作已经表明这变得非常慢。 我怀疑有一种方法可以更快地完成它,而无需循环,但我到目前为止还无法做到这一点。

作为第一步,我可以过滤 df1 中的行

df1['Fecha'].isin(df2['Fecha'].values)

笔记:

  1. 我接下来需要用 df3 等重复该操作,附加到 df1 中的其他行。我不想删除重复项。
  2. df2 中的制服跳绳是捏造的案例。
  3. 附加完成后,我想为每行的平均值创建一列,为标准偏差创建另一列。
  4. 创建我的dfs的代码
    import datetime
    import pandas as pd
    yy = 2001
    date_list = ['{:4d}-{:02d}-{:02d}'.format(yy, mm, dd) for mm in range(1, 2) for dd in range(1, 10)]
    fechas1 = [datetime.datetime.strptime(date_base, '%Y-%m-%d') for date_base in date_list]
    nf1 = len(fechas1)
    vals1 = [[] for _ in range(nf1)]
    dic1 = { 'Fecha': fechas1, 'Vals': vals1 }
    df1 = pd.DataFrame(dic1)
    fechas2 = [datetime.datetime.strptime(date_list[idx], '%Y-%m-%d') for idx in range(0, nf1, 2)]
    nf2 = len(fechas2)
    vals2 = [float(idx) for idx in range(nf2)]
    dic2 = { 'Fecha': fechas2, 'Vals': vals2 }
    df2 = pd.DataFrame(dic2)
    

    有关的:

    1. Python intersection of 2 dataframes with list-type columns
    2. How to append list of values to a column of list in dataframe
    3. Python appending a list to dataframe column
    4. Pandas dataframe append to column containing list
    5. Define a column type as 'list' in Pandas
    6. https://towardsdatascience.com/dealing-with-list-values-in-pandas-dataframes-a177e534f173

【问题讨论】:

  • 如果你想列表存储在列中,那么你最好使用 numpy 数组字典
  • 一旦你在列中有了一个对象类型(就像一个列表),你就摧毁了对其进行矢量化操作的所有希望。列应包含标量
  • @roganjosh - 我不知道原因,你介意澄清一下吗?另外,我会失去pandas 周围的强大资源,以及我自己为这种情况编写的大量代码。所以我需要非常充分的理由才能离开预期的路径。
  • 您几乎没有 pandas 的“强大资源”,因为几乎所有您想对该列执行的操作都必须放到 python 中(例如,使用 lambda)。 pandas 包裹 numpy 的好处是矢量化数值运算,可以将其推送到优化的 C 代码中,而不是坐在 python 本身中
  • @roganjosh - 所以你说不可能在不循环的情况下追加到列中的列表元素?

标签: python pandas list dataframe


【解决方案1】:

您可以使用 merge 而不是循环和几个 lambda 像这样更新不匹配的行 -

import pandas as pd

df1 = pd.DataFrame({'Fecha': ['2001-01-01', '2001-01-02', '2001-01-03', '2001-01-04', '2001-01-05', '2001-01-06', '2001-01-07', '2001-01-08', '2001-01-09'], 'Vals': [[] for _ in range(9)]})
df2 = pd.DataFrame({'Fecha': ['2001-01-01', '2001-01-03', '2001-01-05', '2001-01-07', '2001-01-09'], 'Vals': [0.0, 1.0, 2.0, 3.0, 4.0]})

# Merge df1 and df2 on the 'Fecha' column, using an outer join
result = pd.merge(df1, df2, on='Fecha', how='left')
# Fill the null values in the 'Vals_y' column with an empty list
result['Vals_y'] = result['Vals_y'].apply(lambda x: [] if pd.isnull(x) else x)
# Append the values in the 'Vals_y' column to the 'Vals_x' column as a new element in a list for all rows where the 'Vals_y' column is not an empty list
result['Vals'] = result.apply(lambda row: row['Vals_x'] + [row['Vals_y']] if pd.notnull(row['Vals_y']) else row['Vals_x'], axis=1)

# drop unnecessary columns
result.drop(['Vals_x', 'Vals_y'], axis=1, inplace=True)
print(result)

输出:

        Fecha   Vals
0  2001-01-01  [0.0]
1  2001-01-02     []
2  2001-01-03  [1.0]
3  2001-01-04     []
4  2001-01-05  [2.0]
5  2001-01-06     []
6  2001-01-07  [3.0]
7  2001-01-08     []
8  2001-01-09  [4.0]

【讨论】:

  • 伟大的。我会检查这段代码。请注意,如注释中所述,我会继续附加来自其他来源的元素,并最终计算每行的 (avg, stdev)。我希望这个世界。
猜你喜欢
  • 2020-09-27
  • 1970-01-01
  • 1970-01-01
  • 2021-05-01
  • 1970-01-01
  • 2019-09-08
  • 2021-02-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多