Как дублировать и изменять строки в кадре данных панд? - PullRequest
0 голосов
/ 03 октября 2018

Я пытаюсь построить кадры данных, используя большой объем данных, хранящихся в текстовых файлах.Однако я не создавал данные, поэтому мне приходится работать с разочаровывающим форматированием, содержащимся в нем.Я не мог заставить свой код работать с большими данными (и почти сломал мой компьютер при этом), поэтому установите меньший фрейм данных, например, так:

    'Value'             ID_1                ID_2
0   11122222            ABC42123            33333
1   21219299            YOF21233            88821
2   00022011            ERE00091            23124
3   75643311;21233332   ROB21288            99421
4   12412421            POW94277            12231;33221
5   54221721            IRS21231;YOU28137   13123

Мое разочарование заключается в использовании точек с запятой вданные.Данные предназначены для представления идентификаторов, но несколько идентификаторов были назначены нескольким переменным.Я хочу повторить эти строки, чтобы можно было искать в данных отдельные идентификаторы и иметь таблицу данных, которая выглядит следующим образом:

    'Value'             ID_1                ID_2
0   11122222            ABC42123            33333
1   21219299            YOF21233            88821
2   00022011            ERE00091            23124
3   75643311            ROB21288            99421
4   21233332            ROB21288            99421
5   12412421            POW94277            12231
6   12412421            POW94277            33221
7   54221721            YOU28137            13123
8   54221721            IRS21231            13123

Переиндексация не является проблемой, если различные идентификаторы остаются связанными сдруг к другу и к их правильным значениям.

К сожалению, все мои попытки разделить данные до сих пор заканчивались полным провалом.Мне удалось настроить функцию, которая повторяет данные, содержащие точку с запятой, анализировать это через мою функцию для каждого столбца, но затем не удается разделить данные.

def delete_dup(df,column):
for a in column:
    location = df.loc[df.duplicated(subset= column, keep=False)]
    for x in location:
        semicolon = df.loc[df[column].str.contains(';', regex=True)]
        duplicate = semicolon.duplicated(subset= column, keep='first')
        tiny_df = semicolon.loc[duplicate]

        split_up = tiny_df[column].str.split(';')

        return pd.concat([df, split_up])



  'Value'              ID_1              ID_2           0
  11122222             ABC42123          33333          NaN
  21219299             YOF21233          88821          NaN
  00022011             ERE00091          23124          NaN
  75643311;21233332    ROB21288          99421          NaN
  12412421             POW94277          12231;33221    NaN
  54221721             IRS21231;YOU28137 13123          NaN
  75643311;21233332    ROB21288          99421          NaN
  54221721             IRS21231;YOU28137 13123          NaN
  12412421             POW94277          12231;33221    NaN
  NaN                  NaN               NaN            [75643311, 21233332]

Мне кажется, что это самый близкий япришел, и это все еще далеко от того, что я хочу.Любые операторы «Если», которые я пытаюсь сделать на фреймах данных, встречаются с «ValueError: Истинное значение DataFrame неоднозначно. Используйте a.empty, a.bool (), a.item (), a.any () илиa.All () «.ошибка, которая так расстраивает читать.Любые идеи о том, как заставить панд делать то, что я хочу?

Ответы [ 2 ]

0 голосов
/ 03 октября 2018

Решение состоит из двух частей.Первый - определить, какие строки имеют точку с запятой, а второй - создать дополнительные строки и объединить их.Первая часть выполняется в contains_sc, а вторая часть выполняется путем итерации по строкам и запуска функции create_additional_rows при обнаружении строки с точкой с запятой.

Надеюсь, это поможет.

In[6]: import pandas as pd

In[7]: df = pd.DataFrame(
  [['1', '2;3', '4', '5'],
  ['A', 'B', 'C', 'D;E'],
  ['T', 'U', 'V;W', 'X']],
  index=['Val', 'ID1', 'ID2']
).T

In[8]: df

Out[8]: 
   Val  ID1  ID2
0    1    A    T
1  2;3    B    U
2    4    C  V;W
3    5  D;E    X

In[9]: contains_sc = df.apply(lambda x: x.str.contains(';'))
In[10]: contains_sc
Out[10]: 
     Val    ID1    ID2
0  False  False  False
1   True  False  False
2  False  False   True
3  False   True  False

In[11]: 
def create_additional_rows(data_row, csc_row, split_char=';'):
    """Given a duplicated row return additional de-duplicated rows."""
    if len(csc_row[csc_row].dropna()) > 1:
      raise ValueError('Expect only a single column with a semicolon')
    col_with_sc = csc_row[csc_row].dropna().index[0]
    retval = []
    for item in data_row.loc[col_with_sc].split(split_char):
      copied = data_row.copy()
      copied.loc[col_with_sc] = item
      retval.append(copied)
    return retval

In[11]: 
  new_rows = []
  for (idx, data_row), (_, csc_row) in zip(df.iterrows(), contains_sc.iterrows()):
    if True not in csc_row.values:
      new_rows.append(data_row)
      continue
    new_rows.extend(create_additional_rows(data_row, csc_row))

  final = pd.concat(new_rows, axis='columns').T.reset_index(drop=True)

In[13]: final
Out[13]: 
  Val ID1 ID2
0   1   A   T
1   2   B   U
2   3   B   U
3   4   C   V
4   4   C   W
5   5   D   X
6   5   E   X
0 голосов
/ 03 октября 2018

Возможно, не самый элегантный способ, но этот всего лишь решает проблему:

Шаг 1

Данныеу нас есть:

df
    'Value'     ID_1        ID_2
0   11122222    ABC42123    33333
1   21219299    YOF21233    88821
2   00022011    ERE00091    23124
3   75643311;21233332   ROB21288    99421
4   12412421    POW94277    12231;33221
5   54221721    IRS21231;YOU28137   13123

Шаг 2

Давайте разделим неправильно ведущие колонки

df["'Value'_Dupe"] = df["'Value'"].apply(lambda x: x.split(";")[1] if len(x.split(";"))>1 else np.NaN)
df["'Value'"] = df["'Value'"].apply(lambda x: x.split(";")[0])
df["ID_1_Dupe"] = df["ID_1"].apply(lambda x: x.split(";")[1] if len(x.split(";"))>1 else np.NaN)
df["ID_1"] = df["ID_1"].apply(lambda x: x.split(";")[0])
df["ID_2_Dupe"] = df["ID_2"].apply(lambda x: x.split(";")[1] if len(x.split(";"))>1 else np.NaN)
df["ID_2"] = df["ID_2"].apply(lambda x: x.split(";")[0])
df

    'Value'     ID_1        ID_2    'Value'_Dupe    ID_1_Dupe   ID_2_Dupe
0   11122222    ABC42123    33333   NaN             NaN          NaN
1   21219299    YOF21233    88821   NaN             NaN          NaN
2   00022011    ERE00091    23124   NaN             NaN          NaN
3   75643311    ROB21288    99421   21233332        NaN          NaN
4   12412421    POW94277    12231   NaN             NaN          33221
5   54221721    IRS21231    13123   NaN             YOU28137     NaN

Шаг 3

Давайте объединим дубликаты с исходными данными в один кадр данных:

df2 = df[pd.notna(df["'Value'_Dupe"])][["'Value'_Dupe","ID_1","ID_2"]]
df2.columns = ["'Value'","ID_1","ID_2"]

df3 = df[pd.notna(df["ID_1_Dupe"])][["'Value'","ID_1_Dupe","ID_2"]]
df3.columns = ["'Value'","ID_1","ID_2"]

df4 = df[pd.notna(df["ID_2_Dupe"])][["'Value'","ID_1","ID_2_Dupe"]]
df4.columns = ["'Value'","ID_1","ID_2"]

df5 = df[["'Value'","ID_1","ID_2"]]

df_result = pd.concat([df5,df2,df3,df4])
df_result



    'Value'     ID_1        ID_2
0   11122222    ABC42123    33333
1   21219299    YOF21233    88821
2   00022011    ERE00091    23124
3   75643311    ROB21288    99421
4   12412421    POW94277    12231
5   54221721    IRS21231    13123
3   21233332    ROB21288    99421
5   54221721    YOU28137    13123
4   12412421    POW94277    33221

Пожалуйста, дайте мне знать, если это решит вашу проблему.

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