如何在数据帧中的列之间进行匹配并保留另一列

2024-05-18 11:17:05 发布

您现在位置:Python中文网/ 问答频道 /正文

我想从数据帧中的一列和其他列中获取匹配。下面是一个例子:

  date        tableNameFrom   tableNameJoin   attributeName
1 29-03-2019  film            language        [film.languageId, language.languageID]
2 30-03-2019  inventory       rental          [invetory.inventoryId, rental.filmId]

在上面的例子中,我想用attributeName在tablenameFrom和tablenameJoin之间进行匹配。但是,我想保留日期列。此处显示所需输出:

  date        tableName    attributeName
1 29-03-2019  film         languageId
2 29-03-2019  language     languageID
3 30-03-2019  inventory    inventoryId
4 30-03-2019  rental       filmId

你知道我该怎么办吗?非常感谢。你知道吗


Tags: 数据datelanguage例子inventoryfilmrentalattributename
3条回答

这可能不是您想要的,但会产生给定数据帧的预期输出:

(df.set_index('date').attributeName.apply(pd.Series).stack()
 .reset_index().drop('level_1', axis=1).set_index('date')[0]
 .str.split('.').apply(pd.Series)
 )

它忽略了tableNameFrometableNameJoin,并假设它们在attributeName中给出。你知道吗

+----+------------+----------+-------------+
|    |       date |        0 |           1 |
|----+------------+----------+-------------|
|  0 | 29-03-2019 |     film |  languageId |
|  1 | 29-03-2019 | language |  languageID |
|  2 | 30-03-2019 | invetory | inventoryId |
|  3 | 30-03-2019 |   rental |      filmId |
+----+------------+----------+-------------+

这里有一种可能的方法avoids using ^{}

原始DataFrame

         date tableNameFrom tableNameJoin                           attributeName
0  29-03-2019          film      language  [film.languageId, language.languageID]
1  30-03-2019     inventory        rental   [invetory.inventoryId, rental.filmId]

步骤1-(1)使用,作为分隔符将attributeName拆分为两个单独的列,(2)删除不需要的方括号([]),(3)删除不需要的列

# 1
df[['tableName','attributeName2']] = df['attributeName'].str.split(',', expand=True)

# 2
df['tableName'] = df['tableName'].str.strip('[')
df['attributeName2'] = df['attributeName2'].str.strip(']')

# 3
df.drop(['attributeName','tableNameFrom','tableNameJoin'], axis=1, inplace=True)

print(df)
         date             tableName        attributeName2
0  29-03-2019       film.languageId   language.languageID
1  30-03-2019  invetory.inventoryId         rental.filmId

第2步-最后,使用this SO post将列tableNameattributeName2中的行拆分为单独的列

df_match = (df.set_index(['date'])
               .stack()
               .str.split('.', expand=True)
               .stack()
               .unstack(-1)
               .reset_index(-1, drop=True)
               .reset_index()
            )
df_match.columns = ['date','tableName','attributeName']

print(df_match)
         date  tableName attributeName
0  29-03-2019       film    languageId
1  29-03-2019   language    languageID
2  30-03-2019   invetory   inventoryId
3  30-03-2019     rental        filmId

细节

  • .set_index(['date']-设置要作为DataFrame的索引保留的列
  • .stack()-堆栈行
  • .str.split('.', expand=True)-呼叫结构拆分在周期(.)上将这些单元格拆分为单独的列
  • .stack()-去掉NULL值,所以再次调用stack
  • .unstack(-1)
    • 因为我们希望索引的最后一级成为我们的列,所以使用unstack(-1)(在最后一级取消堆栈)取消堆栈
    • 我已经在下面详细说明了这一点1
  • .reset_index(-1, drop=True)-使用reset_index(-1)消除多余的最后一级

1这里是.unstack(-1)步骤之前的输出,并解释了为什么需要在unstack()内使用-1

df_intermediate = (df.set_index(['date'])
                       .stack()
                       .str.split('.', expand=True)
                       .stack()
                )

print(df_intermediate)
date                         
29-03-2019  tableName       0           film
                            1     languageId
            attributeName2  0       language
                            1     languageID
30-03-2019  tableName       0       invetory
                            1    inventoryId
            attributeName2  0         rental
                            1         filmId
dtype: object
  • 这表明我们希望最后一个索引级别(值为0,1)成为列,因此我们在.unstack(-1)中选择-1
df.drop(["tableNameFrom","tableNameJoin"],inplace=True)
df2=pd.DataFrame()
for row in df.itertuples():
    for i in range(2):
        df2=df2.append(pd.Series(
            [row[1],"".join(row[2][i].split('.')[0]),"".join(row[2][i].split('.')[1])]).T,ignore_index=True)
df2.columns=["date","tableName","tableAttribute"]
df2

我不明白你为什么需要中间的两根柱子,所以我把它们扔了。你知道吗

相关问题 更多 >