Как сопоставить столбцы в кадре данных и сохранить другой столбец - PullRequest
0 голосов
/ 22 апреля 2019

Я хотел бы получить совпадения из одного столбца с другими столбцами в кадре данных. Ниже приведен пример:

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

В приведенном выше примере я хотел бы сопоставить tablenameFrom и tablenameJoin с attributeName. Но я хочу сохранить столбец date . Здесь желаемый вывод:

  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

Есть идеи, что мне делать? Спасибо.

Ответы [ 4 ]

2 голосов
/ 22 апреля 2019

Возможно, это не то, что вам нужно, но выдает ожидаемый вывод для данного кадра данных:

(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)
 )

Он игнорирует tableNameFrome и tableNameJoin и предполагает, что они приведены в 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 |
+----+------------+----------+-------------+
1 голос
/ 22 апреля 2019

Это в основном проблема melt, но с промежуточным шагом для очистки столбца attributeName:


# Clean up attributeName column by converting it to string and expanding it by splitting
df = pd.concat([df, df.attributeName.apply(lambda x: ' '.join(x).split('.')[1]).str.split(expand=True)], axis=1)\
     .drop('attributeName', axis=1)\
     .rename({0:'attribute1', 1:'attribute2'}, axis=1)

, который дает нам следующий фрейм данных:

print(df)
         date tableNameFrom tableNameJoin   attribute1 attribute2
0  29-03-2019          film      language   languageId   language
1  30-03-2019     inventory        rental  inventoryId     rental

Затем мы можем использовать melt дважды, чтобы получить желаемый результат:

df1 = df.melt(id_vars='date', value_vars=['tableNameFrom', 'tableNameJoin'], value_name='tableName').drop('variable', axis=1)
df2 = df.melt(id_vars='date', value_vars=['attribute1', 'attribute2'], value_name='attributeName').drop(['variable', 'date'], axis=1)

df = pd.concat([df1, df2], axis=1)

Что дает нам окончательный результат:

print(df)
        date  tableName attributeName
0  29-03-2019       film    languageId
1  30-03-2019  inventory   inventoryId
2  29-03-2019   language      language
3  30-03-2019     rental        rental
1 голос
/ 22 апреля 2019

Вот один из возможных подходов, который избегает использования apply

Сырье 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 отдельных столбца, используя , в качестве разделителя, (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 - Наконец, используйте этот пост SO , чтобы разбить строки из столбцов tableName и attributeName2 на отдельные столбцы

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) - вызвать str.split по периоду (.), чтобы разбить эти ячейки на отдельные столбцы
  • .stack() - избавиться от NULL значений, поэтому снова вызвать stack
  • .unstack(-1)
    • , так как мы хотим, чтобы последний уровень индекса стал нашими столбцами, поэтому отмените стек, используя unstack(-1) (отмените стек на последнем уровне)
    • Я показал это подробно ниже 1
  • .reset_index(-1, drop=True) - устранить лишний последний уровень, используя reset_index(-1)

1 Вот вывод перед шагом .unstack(-1) и объяснение того, почему нам нужно использовать -1 внутри unstack()

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) стал столбцами, поэтому мы выбираем -1 в .unstack(-1)
1 голос
/ 22 апреля 2019
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

не понимаю, зачем вам две средние колонки, поэтому я уронил их.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...