ฉันมี dataframe 20 x 4000 ใน Python โดยใช้แพนด้า สองคอลัมน์เหล่านี้จะถูกตั้งชื่อและYear
quarter
ฉันต้องการที่จะสร้างตัวแปรที่เรียกว่าperiod
ทำให้Year = 2000
และเข้าquarter= q2
2000q2
มีใครสามารถช่วยได้บ้าง
ฉันมี dataframe 20 x 4000 ใน Python โดยใช้แพนด้า สองคอลัมน์เหล่านี้จะถูกตั้งชื่อและYear
quarter
ฉันต้องการที่จะสร้างตัวแปรที่เรียกว่าperiod
ทำให้Year = 2000
และเข้าquarter= q2
2000q2
มีใครสามารถช่วยได้บ้าง
คำตอบ:
หากทั้งสองคอลัมน์เป็นสตริงคุณสามารถต่อกันได้โดยตรง:
df["period"] = df["Year"] + df["quarter"]
หากหนึ่ง (หรือทั้งสอง) ของคอลัมน์ไม่ได้เป็นสตริงที่พิมพ์คุณควรแปลงมัน (พวกเขา) ก่อน
df["period"] = df["Year"].astype(str) + df["quarter"]
หากคุณต้องการเข้าร่วมหลายคอลัมน์สตริงคุณสามารถใช้agg
:
df['period'] = df[['Year', 'quarter', ...]].agg('-'.join, axis=1)
โดยที่ "-" เป็นตัวคั่น
sum
ที่ควรจะเป็นไปได้ด้วยในตัวงูหลาม
dataframe["period"] = dataframe["Year"].map(str) + dataframe["quarter"].map(str)
แผนที่เพียงแค่ใช้การแปลงสตริงกับรายการทั้งหมด
df = pd.DataFrame({'Year': ['2014', '2015'], 'quarter': ['q1', 'q2']})
df['period'] = df[['Year', 'quarter']].apply(lambda x: ''.join(x), axis=1)
ให้ผลกับดาต้าเฟรมนี้
Year quarter period
0 2014 q1 2014q1
1 2015 q2 2015q2
วิธีนี้ทำให้จำนวนคอลัมน์สตริงเป็นแบบทั่วไปโดยแทนที่df[['Year', 'quarter']]
ด้วยส่วนแบ่งคอลัมน์ใด ๆ ของ dataframe ของคุณเช่นdf.iloc[:,0:2].apply(lambda x: ''.join(x), axis=1)
ของคุณเช่น
คุณสามารถตรวจสอบข้อมูลเพิ่มเติมเกี่ยวกับวิธีการสมัคร () ได้ที่นี่
lambda x: ''.join(x)
เป็นเพียง''.join
ไม่
lambda x: ''.join(x)
ก่อสร้างไม่ได้ทำอะไรเลย มันก็เหมือนใช้แทนเพียงlambda x: sum(x)
sum
''.join
df['period'] = df[['Year', 'quarter']].apply(''.join, axis=1)
join
ใช้str
อินสแตนซ์ในการวนซ้ำเท่านั้น ใช้map
การแปลงพวกเขาทั้งหมดลงแล้วใช้str
join
[''.join(i) for i in zip(df["Year"].map(str),df["quarter"])]
หรือช้ากว่าเล็กน้อย แต่กะทัดรัดกว่า:
df.Year.str.cat(df.quarter)
df['Year'].astype(str) + df['quarter']
UPDATE:กราฟเวลา Pandas 0.23.4
ลองทดสอบด้วยแถว 200K DF:
In [250]: df
Out[250]:
Year quarter
0 2014 q1
1 2015 q2
In [251]: df = pd.concat([df] * 10**5)
In [252]: df.shape
Out[252]: (200000, 2)
อัปเดต:กำหนดเวลาใหม่โดยใช้ Pandas 0.19.0
การจับเวลาโดยไม่มีการเพิ่มประสิทธิภาพ CPU / GPU (เรียงลำดับจากเร็วไปช้า):
In [107]: %timeit df['Year'].astype(str) + df['quarter']
10 loops, best of 3: 131 ms per loop
In [106]: %timeit df['Year'].map(str) + df['quarter']
10 loops, best of 3: 161 ms per loop
In [108]: %timeit df.Year.str.cat(df.quarter)
10 loops, best of 3: 189 ms per loop
In [109]: %timeit df.loc[:, ['Year','quarter']].astype(str).sum(axis=1)
1 loop, best of 3: 567 ms per loop
In [110]: %timeit df[['Year','quarter']].astype(str).sum(axis=1)
1 loop, best of 3: 584 ms per loop
In [111]: %timeit df[['Year','quarter']].apply(lambda x : '{}{}'.format(x[0],x[1]), axis=1)
1 loop, best of 3: 24.7 s per loop
เวลาโดยใช้การเพิ่มประสิทธิภาพ CPU / GPU:
In [113]: %timeit df['Year'].astype(str) + df['quarter']
10 loops, best of 3: 53.3 ms per loop
In [114]: %timeit df['Year'].map(str) + df['quarter']
10 loops, best of 3: 65.5 ms per loop
In [115]: %timeit df.Year.str.cat(df.quarter)
10 loops, best of 3: 79.9 ms per loop
In [116]: %timeit df.loc[:, ['Year','quarter']].astype(str).sum(axis=1)
1 loop, best of 3: 230 ms per loop
In [117]: %timeit df[['Year','quarter']].astype(str).sum(axis=1)
1 loop, best of 3: 230 ms per loop
In [118]: %timeit df[['Year','quarter']].apply(lambda x : '{}{}'.format(x[0],x[1]), axis=1)
1 loop, best of 3: 9.38 s per loop
ตอบผลงานโดย @ anton-vbr
df.T.apply(lambda x: x.str.cat(sep=''))
วิธีการcat()
ของ.str
accessor ใช้งานได้ดีในเรื่องนี้:
>>> import pandas as pd
>>> df = pd.DataFrame([["2014", "q1"],
... ["2015", "q3"]],
... columns=('Year', 'Quarter'))
>>> print(df)
Year Quarter
0 2014 q1
1 2015 q3
>>> df['Period'] = df.Year.str.cat(df.Quarter)
>>> print(df)
Year Quarter Period
0 2014 q1 2014q1
1 2015 q3 2015q3
cat()
แม้อนุญาตให้คุณเพิ่มตัวคั่นได้ตัวอย่างเช่นสมมติว่าคุณมีจำนวนเต็มสำหรับปีและช่วงเวลาเท่านั้นคุณสามารถทำได้:
>>> import pandas as pd
>>> df = pd.DataFrame([[2014, 1],
... [2015, 3]],
... columns=('Year', 'Quarter'))
>>> print(df)
Year Quarter
0 2014 1
1 2015 3
>>> df['Period'] = df.Year.astype(str).str.cat(df.Quarter.astype(str), sep='q')
>>> print(df)
Year Quarter Period
0 2014 1 2014q1
1 2015 3 2015q3
การเข้าร่วมหลายคอลัมน์เป็นเพียงเรื่องของการส่งรายการชุดข้อมูลหรือ dataframe ที่มีทั้งหมด แต่คอลัมน์แรกเป็นพารามิเตอร์ที่จะstr.cat()
เรียกใช้ในคอลัมน์แรก (ชุดข้อมูล):
>>> df = pd.DataFrame(
... [['USA', 'Nevada', 'Las Vegas'],
... ['Brazil', 'Pernambuco', 'Recife']],
... columns=['Country', 'State', 'City'],
... )
>>> df['AllTogether'] = df['Country'].str.cat(df[['State', 'City']], sep=' - ')
>>> print(df)
Country State City AllTogether
0 USA Nevada Las Vegas USA - Nevada - Las Vegas
1 Brazil Pernambuco Recife Brazil - Pernambuco - Recife
โปรดทราบว่าหากแพนด้า dataframe / series ของคุณมีค่า Null คุณจะต้องรวมพารามิเตอร์ na_rep เพื่อแทนที่ค่า NaN ด้วยสตริงมิฉะนั้นคอลัมน์ที่รวมกันจะเริ่มต้นเป็น NaN
lambda
หรือmap
; มันก็แค่อ่านอย่างหมดจดที่สุด
str.cat()
แทนของซีรีส์เป็นพารามิเตอร์แรกจะเป็น ฉันจะแก้ไขคำตอบ
sep
คำสำคัญหรือไม่? ใน pandas-0.23.4 ขอบคุณ!
sep
พารามิเตอร์เป็นสิ่งจำเป็นเท่านั้นถ้าคุณตั้งใจจะแยกส่วนของการตัดแบ่งสตริง หากคุณได้รับข้อผิดพลาดโปรดแสดงตัวอย่างความล้มเหลวของคุณให้เราทราบ
การใช้ฟังก์ชั่น lamba ครั้งนี้กับ string.format ()
import pandas as pd
df = pd.DataFrame({'Year': ['2014', '2015'], 'Quarter': ['q1', 'q2']})
print df
df['YearQuarter'] = df[['Year','Quarter']].apply(lambda x : '{}{}'.format(x[0],x[1]), axis=1)
print df
Quarter Year
0 q1 2014
1 q2 2015
Quarter Year YearQuarter
0 q1 2014 2014q1
1 q2 2015 2015q2
สิ่งนี้ช่วยให้คุณทำงานกับค่าที่ไม่ใช่สตริงและฟอร์แมตใหม่ได้ตามต้องการ
import pandas as pd
df = pd.DataFrame({'Year': ['2014', '2015'], 'Quarter': [1, 2]})
print df.dtypes
print df
df['YearQuarter'] = df[['Year','Quarter']].apply(lambda x : '{}q{}'.format(x[0],x[1]), axis=1)
print df
Quarter int64
Year object
dtype: object
Quarter Year
0 1 2014
1 2 2015
Quarter Year YearQuarter
0 1 2014 2014q1
1 2 2015 2015q2
คำตอบง่ายๆสำหรับคำถามของคุณ
year quarter
0 2000 q1
1 2000 q2
> df['year_quarter'] = df['year'] + '' + df['quarter']
> print(df['year_quarter'])
2000q1
2000q2
Year
ไม่ใช่สตริง
df['Year'].astype(str) + '' + df['quarter'].astype(str)
ถึงแม้ว่าคำตอบ @silvado เป็นสิ่งที่ดีถ้าคุณเปลี่ยนdf.map(str)
ไปdf.astype(str)
มันจะเร็วขึ้น:
import pandas as pd
df = pd.DataFrame({'Year': ['2014', '2015'], 'quarter': ['q1', 'q2']})
In [131]: %timeit df["Year"].map(str)
10000 loops, best of 3: 132 us per loop
In [132]: %timeit df["Year"].astype(str)
10000 loops, best of 3: 82.2 us per loop
ขอให้เราคิดว่าคุณ dataframe
มีที่df
มีคอลัมน์และYear
Quarter
import pandas as pd
df = pd.DataFrame({'Quarter':'q1 q2 q3 q4'.split(), 'Year':'2000'})
สมมติว่าเราต้องการดูดาต้าเฟรม
df
>>> Quarter Year
0 q1 2000
1 q2 2000
2 q3 2000
3 q4 2000
สุดท้ายเชื่อมต่อYear
และQuarter
ดังต่อไปนี้
df['Period'] = df['Year'] + ' ' + df['Quarter']
ตอนนี้คุณสามารถprint
df
ดู dataframe ที่ได้
df
>>> Quarter Year Period
0 q1 2000 2000 q1
1 q2 2000 2000 q2
2 q3 2000 2000 q3
3 q4 2000 2000 q4
หากคุณไม่ต้องการให้มีช่องว่างระหว่างปีกับไตรมาสเพียงแค่ลบออกโดยทำ
df['Period'] = df['Year'] + df['Quarter']
df['Period'] = df['Year'].map(str) + df['Quarter'].map(str)
TypeError: Series cannot perform the operation +
เมื่อใช้อย่างใดอย่างหนึ่งหรือdf2['filename'] = df2['job_number'] + '.' + df2['task_number']
df2['filename'] = df2['job_number'].map(str) + '.' + df2['task_number'].map(str)
df2['filename'] = df2['job_number'].astype(str) + '.' + df2['task_number'].astype(str)
ทำงานได้ดี
dataframe
ที่ฉันสร้างไว้ด้านบนคุณจะเห็นว่าคอลัมน์ทั้งหมดเป็นstring
ของ
นี่คือการใช้งานที่ฉันพบว่าหลากหลายมาก:
In [1]: import pandas as pd
In [2]: df = pd.DataFrame([[0, 'the', 'quick', 'brown'],
...: [1, 'fox', 'jumps', 'over'],
...: [2, 'the', 'lazy', 'dog']],
...: columns=['c0', 'c1', 'c2', 'c3'])
In [3]: def str_join(df, sep, *cols):
...: from functools import reduce
...: return reduce(lambda x, y: x.astype(str).str.cat(y.astype(str), sep=sep),
...: [df[col] for col in cols])
...:
In [4]: df['cat'] = str_join(df, '-', 'c0', 'c1', 'c2', 'c3')
In [5]: df
Out[5]:
c0 c1 c2 c3 cat
0 0 the quick brown 0-the-quick-brown
1 1 fox jumps over 1-fox-jumps-over
2 2 the lazy dog 2-the-lazy-dog
เมื่อข้อมูลของคุณถูกแทรกลงใน dataframe คำสั่งนี้ควรแก้ปัญหาของคุณ:
df['period'] = df[['Year', 'quarter']].apply(lambda x: ' '.join(x.astype(str)), axis=1)
มีประสิทธิภาพมากขึ้นคือ
def concat_df_str1(df):
""" run time: 1.3416s """
return pd.Series([''.join(row.astype(str)) for row in df.values], index=df.index)
และนี่คือการทดสอบเวลา:
import numpy as np
import pandas as pd
from time import time
def concat_df_str1(df):
""" run time: 1.3416s """
return pd.Series([''.join(row.astype(str)) for row in df.values], index=df.index)
def concat_df_str2(df):
""" run time: 5.2758s """
return df.astype(str).sum(axis=1)
def concat_df_str3(df):
""" run time: 5.0076s """
df = df.astype(str)
return df[0] + df[1] + df[2] + df[3] + df[4] + \
df[5] + df[6] + df[7] + df[8] + df[9]
def concat_df_str4(df):
""" run time: 7.8624s """
return df.astype(str).apply(lambda x: ''.join(x), axis=1)
def main():
df = pd.DataFrame(np.zeros(1000000).reshape(100000, 10))
df = df.astype(int)
time1 = time()
df_en = concat_df_str4(df)
print('run time: %.4fs' % (time() - time1))
print(df_en.head(10))
if __name__ == '__main__':
main()
ขั้นสุดท้ายเมื่อใช้sum
(concat_df_str2) ผลลัพธ์จะไม่เพียงแค่ concat มันจะเปลี่ยนเป็นจำนวนเต็ม
df.values[:, 0:3]
df.values[:, [0,2]]
การสรุปเป็นหลายคอลัมน์ทำไมไม่:
columns = ['whatever', 'columns', 'you', 'choose']
df['period'] = df[columns].astype(str).sum(axis=1)
การใช้zip
อาจเร็วกว่า:
df["period"] = [''.join(i) for i in zip(df["Year"].map(str),df["quarter"])]
กราฟ:
import pandas as pd
import numpy as np
import timeit
import matplotlib.pyplot as plt
from collections import defaultdict
df = pd.DataFrame({'Year': ['2014', '2015'], 'quarter': ['q1', 'q2']})
myfuncs = {
"df['Year'].astype(str) + df['quarter']":
lambda: df['Year'].astype(str) + df['quarter'],
"df['Year'].map(str) + df['quarter']":
lambda: df['Year'].map(str) + df['quarter'],
"df.Year.str.cat(df.quarter)":
lambda: df.Year.str.cat(df.quarter),
"df.loc[:, ['Year','quarter']].astype(str).sum(axis=1)":
lambda: df.loc[:, ['Year','quarter']].astype(str).sum(axis=1),
"df[['Year','quarter']].astype(str).sum(axis=1)":
lambda: df[['Year','quarter']].astype(str).sum(axis=1),
"df[['Year','quarter']].apply(lambda x : '{}{}'.format(x[0],x[1]), axis=1)":
lambda: df[['Year','quarter']].apply(lambda x : '{}{}'.format(x[0],x[1]), axis=1),
"[''.join(i) for i in zip(dataframe['Year'].map(str),dataframe['quarter'])]":
lambda: [''.join(i) for i in zip(df["Year"].map(str),df["quarter"])]
}
d = defaultdict(dict)
step = 10
cont = True
while cont:
lendf = len(df); print(lendf)
for k,v in myfuncs.items():
iters = 1
t = 0
while t < 0.2:
ts = timeit.repeat(v, number=iters, repeat=3)
t = min(ts)
iters *= 10
d[k][lendf] = t/iters
if t > 2: cont = False
df = pd.concat([df]*step)
pd.DataFrame(d).plot().legend(loc='upper center', bbox_to_anchor=(0.5, -0.15))
plt.yscale('log'); plt.xscale('log'); plt.ylabel('seconds'); plt.xlabel('df rows')
plt.show()
วิธีที่ง่ายที่สุด:
โซลูชันทั่วไป
df['combined_col'] = df[['col1', 'col2']].astype(str).apply('-'.join, axis=1)
การแก้ปัญหาเฉพาะคำถาม
df['quarter_year'] = df[['quarter', 'year']].astype(str).apply(''.join, axis=1)
ระบุตัวคั่นที่ต้องการภายในเครื่องหมายคำพูดก่อน. join
โซลูชันนี้ใช้ขั้นตอนกลางที่บีบอัดสองคอลัมน์ของ DataFrame ไปยังคอลัมน์เดียวที่มีรายการค่า สิ่งนี้ใช้ได้กับสตริงเท่านั้น แต่สำหรับคอลัมน์ -type ทุกชนิด
import pandas as pd
df = pd.DataFrame({'Year': ['2014', '2015'], 'quarter': ['q1', 'q2']})
df['list']=df[['Year','quarter']].values.tolist()
df['period']=df['list'].apply(''.join)
print(df)
ผลลัพธ์:
Year quarter list period
0 2014 q1 [2014, q1] 2014q1
1 2015 q2 [2015, q2] 2015q2
ดังที่หลายคนได้กล่าวถึงก่อนหน้านี้คุณต้องแปลงแต่ละคอลัมน์เป็นสตริงแล้วใช้ตัวดำเนินการบวกเพื่อรวมคอลัมน์สตริงสองคอลัมน์ คุณสามารถเพิ่มประสิทธิภาพได้อย่างมากโดยใช้ NumPy
%timeit df['Year'].values.astype(str) + df.quarter
71.1 ms ± 3.76 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit df['Year'].astype(str) + df['quarter']
565 ms ± 22.3 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
df2['filename'] = df2['job_number'].values.astype(str) + '.' + df2['task_number'].values.astype(str)
-> เอาท์พุทTypeError: ufunc 'add' did not contain a loop with signature matching types dtype('<U21') dtype('<U21') dtype('<U21')
: ทั้ง job_number และ task_number เป็น ints
df['Year'].values.astype(str) + df.quarter
ฉันคิดว่าวิธีที่ดีที่สุดในการรวมคอลัมน์ในแพนด้าคือการแปลงทั้งคอลัมน์เป็นจำนวนเต็มแล้วเปลี่ยนเป็น str
df[['Year', 'quarter']] = df[['Year', 'quarter']].astype(int).astype(str)
df['Period']= df['Year'] + 'q' + df['quarter']
นี่คือบทสรุปของฉันของโซลูชันด้านบนเพื่อต่อ / รวมสองคอลัมน์เข้ากับค่า int และ str ในคอลัมน์ใหม่โดยใช้ตัวคั่นระหว่างค่าของคอลัมน์ โซลูชันสามตัวทำงานเพื่อจุดประสงค์นี้
# be cautious about the separator, some symbols may cause "SyntaxError: EOL while scanning string literal".
# e.g. ";;" as separator would raise the SyntaxError
separator = "&&"
# pd.Series.str.cat() method does not work to concatenate / combine two columns with int value and str value. This would raise "AttributeError: Can only use .cat accessor with a 'category' dtype"
df["period"] = df["Year"].map(str) + separator + df["quarter"]
df["period"] = df[['Year','quarter']].apply(lambda x : '{} && {}'.format(x[0],x[1]), axis=1)
df["period"] = df.apply(lambda x: f'{x["Year"]} && {x["quarter"]}', axis=1)
def madd(x):
"""Performs element-wise string concatenation with multiple input arrays.
Args:
x: iterable of np.array.
Returns: np.array.
"""
for i, arr in enumerate(x):
if type(arr.item(0)) is not str:
x[i] = x[i].astype(str)
return reduce(np.core.defchararray.add, x)
ตัวอย่างเช่น:
data = list(zip([2000]*4, ['q1', 'q2', 'q3', 'q4']))
df = pd.DataFrame(data=data, columns=['Year', 'quarter'])
df['period'] = madd([df[col].values for col in ['Year', 'quarter']])
df
Year quarter period
0 2000 q1 2000q1
1 2000 q2 2000q2
2 2000 q3 2000q3
3 2000 q4 2000q4
หนึ่งสามารถใช้วิธีการมอบหมายของDataFrame :
df= (pd.DataFrame({'Year': ['2014', '2015'], 'quarter': ['q1', 'q2']}).
assign(period=lambda x: x.Year+x.quarter ))
dataframe["period"] = dataframe["Year"].astype(str).add(dataframe["quarter"])
หรือถ้าค่าเป็น [2000] [4] และต้องการสร้าง [2000q4]
dataframe["period"] = dataframe["Year"].astype(str).add('q').add(dataframe["quarter"]).astype(str)
แทน.astype(str)
ด้วย.map(str)
งานเกินไป
add(dataframe.iloc[:, 0:10])
เป็นตัวอย่าง?